Pendugaan Parameter, Diagnostik Model, dan Peramalan

Angga Fathan Rofiqy

28 October, 2023

Kode di Hide dalam default, untuk menampilkan kode, klik Code .

#                      -=( Install & Load Package Function )=-
install_load <- function (package1, ...)  {   

   # convert arguments to vector
   packages <- c(package1, ...)

   # start loop to determine if each package is installed
   for(package in packages){

       # if package is installed locally, load
       if(package %in% rownames(installed.packages()))
          do.call('library', list(package))

       # if package is not installed locally, download, then load
       else {
          install.packages(package)
          do.call("library", list(package))
       }
   } 
}
path <- function(){
  gsub  ( "\\\\",  "/",  readClipboard ()  )
}
#Copy path, Panggil function di console
#Copy r path, paste ke var yang diinginkan
#Export chart
export.chart <- "C:/Users/Fathan/Documents/Obsidian Vault/2. Kuliah/Smt 5/6. Metode Peramalan Deret Waktu/@Proj/STA1341-MPDW/Pertemuan 8/Chart"

1 Pendahuluan

Dataset yang saya gunakan merupakan koleksi data harga saham historis periode Juli 2018 hingga Juli 2023 dari tujuh raksasa teknologi paling berpengaruh di dunia: Microsoft, Apple, Amazon, Nvidia, Google, Netflix, dan Meta (sebelumnya dikenal sebagai Facebook). Dataset ini menjadi sumber daya berharga bagi analis keuangan, ilmuwan data, dan penggemar pasar saham yang ingin menganalisis dan memahami tren harga perusahaan-perusahaan terkemuka di industri ini.

Dataset ini memilki data :

  1. Open: yakni Harga saham pada awal periode perdagangan tertentu. Ini adalah harga saham pertama pada hari perdagangan tersebut.
  2. High: Harga tertinggi yang saham capai selama periode perdagangan tersebut. Ini mencerminkan harga tertinggi yang pembeli bersedia bayar selama hari tersebut.
  3. Low: Harga terendah yang saham capai selama periode perdagangan tersebut. Ini mencerminkan harga terendah yang penjual bersedia terima selama hari tersebut.
  4. Close: Harga saham pada akhir periode perdagangan tertentu. Ini adalah harga saham terakhir pada hari perdagangan tersebut.
  5. Adj Close (Adjusted Close): Harga penutup yang telah disesuaikan untuk memperhitungkan perubahan seperti pembagian saham atau dividen. Ini adalah harga penutup yang paling relevan untuk analisis jangka panjang, karena mencerminkan harga saham yang sebenarnya setelah penyesuaian.
  6. Volume: Volume perdagangan saham selama periode tertentu. Ini mencerminkan jumlah saham yang diperdagangkan selama hari perdagangan tersebut.

Kami akan menggunakan peubah Adj Close (Adjusted Close), Karena sesuai dengan penjelasan diatas, peubah Adj Close adalah yang paling sesuai untuk dianalisis dibandingkan peubah lainnya.

1.1 Tujuan

Tujuan dari praktikum ini adalah untuk menganalisis pola perkiraan pergerakan harga tujuh saham teknologi terkemuka dengan harapan dapat memberikan rekomendasi kepada pembaca mengenai saham mana yang sebaiknya dipertimbangkan untuk dibeli atau diinvestasikan secara signifikan di antara tujuh perusahaan teknologi besar tersebut.

1.2 Referensi

1.3 Data Preparation

1.3.1 Import Data

install_load('rio')
raw.data <- import("https://raw.githubusercontent.com/Zen-Rofiqy/STA1341-MPDW/main/Data/MAANG%20Stock%20Prices.csv")

1.3.2 Data Checking

Cek Tipe data.

str(raw.data)
## 'data.frame':    8812 obs. of  8 variables:
##  $ Name     : chr  "AMZN" "AMZN" "AMZN" "AMZN" ...
##  $ Date     : chr  "7/30/18" "7/31/18" "8/1/18" "8/2/18" ...
##  $ Open     : chr  "91.366501" "89.324501" "89.199997" "89.438499" ...
##  $ High     : chr  "91.474998" "90.091499" "89.921997" "91.828003" ...
##  $ Low      : chr  "88.301003" "86.966003" "88.801003" "89.300003" ...
##  $ Close    : chr  "88.960999" "88.872002" "89.858498" "91.716499" ...
##  $ Adj Close: chr  "88.960999" "88.872002" "89.858498" "91.716499" ...
##  $ Volume   : chr  "131246000" "114774000" "83062000" "87094000" ...

Semua data Karakter, harus diubah.

Cek Data kosong.

sum(is.na(raw.data))
## [1] 0

Tidak ada data kosong.

1.3.3 Penyesuaian Tipe Data

Semua tipe data masih berupa character. Harus diubah menjadi tipe data yang sesuai.

install_load('dplyr')
data <- raw.data %>%  
  mutate(
    Date = as.Date(raw.data[, 2], format = "%m/%d/%y"), #Mengubah menjadi Date 
    across(3:ncol(raw.data), as.numeric)                #Mengubah menjadi Numerik
  )
str(data)
## 'data.frame':    8812 obs. of  8 variables:
##  $ Name     : chr  "AMZN" "AMZN" "AMZN" "AMZN" ...
##  $ Date     : Date, format: "2018-07-30" "2018-07-31" ...
##  $ Open     : num  91.4 89.3 89.2 89.4 91.9 ...
##  $ High     : num  91.5 90.1 89.9 91.8 92.1 ...
##  $ Low      : num  88.3 87 88.8 89.3 91.1 ...
##  $ Close    : num  89 88.9 89.9 91.7 91.2 ...
##  $ Adj Close: num  89 88.9 89.9 91.7 91.2 ...
##  $ Volume   : num  1.31e+08 1.15e+08 8.31e+07 8.71e+07 6.92e+07 ...

1.3.4 Rechecking Data 

Cek kembali data kosong.

cat('Banyaknya Data Kosong', sum(is.na(data)))
## Banyaknya Data Kosong 42

Melihat baris, kolom mana data yang kosong.

# Mencari indeks baris dan kolom yang mengandung NA
na.idx <- which(is.na(data), arr.ind = TRUE)

# Menampilkan data raw dengan baris dan kolom yang mengandung NA
install_load('DT')
datatable(raw.data[                        # Subsetting
                unique(na.idx[, 1]),   # Vektor indeks baris yang mengandung NA
                unique(na.idx[, 2])  ] # Vektor indeks kolom yang mengandung NA
          )  

Ternyata pada baris tersebut ada data karakter text yang merupakan label dari tiap kolomnya. Sehingga ketika diubah ke numerik akan menjadi NA. Maka saya akan menghapus baris tersebut.

1.3.5 Data Cleaned

data <- data %>%
  filter(!row_number() %in% unique(na.idx[, 1]))
datatable(data, filter = 'top', 
          options = list(pageLength = 5))

1.4 Eksplorasi Data

install_load('ggplot2','extrafont')
# font_import(); loadfonts() #Run ini sekali aja
theme.ts <- list(
  theme(legend.position = "none",
        axis.text.x = element_text(hjust = 1, 
                                   margin = margin(b = 10, t=20)),
        axis.text.y = element_text(vjust = 0.5, face = "bold", 
                                   margin = margin(l = 20, r = 20)),
        plot.title = element_text(hjust = 0.5, face = "bold"),
        text = element_text(size = 30),
        plot.subtitle = element_text(hjust = 0.5),
        panel.background = element_rect(fill = 'transparent'),
        plot.background = element_rect(fill='transparent', color=NA),
        panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        axis.line = element_line(linewidth = 1, colour = "black"))
        )
theme.ts1 <- list(
  theme(legend.position = "none",
        axis.text.x = element_text(hjust = 1, 
                                   margin = margin(b = 10, t=20)),
        axis.text.y = element_text(vjust = 0.5, face = "bold", 
                                   margin = margin(l = 50, r = 20)),
        plot.title = element_text(hjust = 0.5, face = "bold"),
        text = element_text(size = 30),
        plot.subtitle = element_text(hjust = 0.5),
        panel.background = element_rect(fill = 'transparent'),
        plot.background = element_rect(fill='transparent', color=NA),
        panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        axis.line = element_line(linewidth = 1, colour = "black"))
        )

1.4.1 Time Series MAANG

Melihat keseluruhan Time Series data saham.

install_load('viridis','ggrepel')
#Plot
chart <-
ggplot(data, aes(x=Date, y=`Adj Close`, color=Name, alpha=Name)) + #Data
  geom_line(aes(color=Name), linewidth=1.5) + #Timeseries
  #Color
  scale_color_manual(values = c(NVDA="green4", NFLX="firebrick3", 
                                MSFT="deepskyblue2", META="dodgerblue3", 
                                AAPL="lightskyblue4",
                                GOOG="gold3", AMZN="orange2") ) +
  scale_alpha_manual(values = c("NVDA" = 1, "NFLX" = .25, "MSFT" = .25, 
                                "META" = .25, "AAPL" = .25, "GOOG" = .25, 
                                "AMZN" = 1)) +
  theme.ts + #THeme
  labs(x = "\nPeriode (Tahun)", y='Harga Saham (USD)',
       title = "Time Series MAANG",
       subtitle = "Seperti apa sih pola deret waktu saham MAANG?\n") +
  # Label / legend
  geom_text_repel(
    data=data[data$Date == max(data$Date),], #Posisi di ujung data
    aes(color = Name, label = Name), #Warna garis & label saham
    size = 8, #Ukuran text
    nudge_x = 80, #Posisi Text (kanan 50)
    hjust = 0, #Ujung
    segment.size = 1,               #Ukuran garis
    segment.alpha = .75,             #transparasi garis
    segment.linetype = "dotted",    #Time garis
    box.padding = .4, #Biar label saham nggak dempetan
    segment.curvature = -0.1, #biar garis mulus
    segment.ncp = 8, 
    segment.angle = 60 
  ) +
  #Axis
    coord_cartesian(clip = "off"
  ) +
    scale_x_date( #Sumbu x
    date_breaks = "1 year",  # Menampilkan label setiap tahun
    date_labels = "%Y",  # Format label tahun
    limits = c(as.Date("2018-07-30"), as.Date("2023-12-28"))
    #Tampilin lebih dari 20023-07-28 agar label saham bisa masuk
  ) +
    scale_y_continuous( #Sumbu y
    labels = scales::dollar_format(prefix = "$") #tambahin dolar
  ) +
    annotate( #Buat nandain batas data
    "text", x = as.Date("2023-7-28"), y = 50, 
    label = "28 Juli", size=6
  ) +
  geom_vline( #Buat garis batas data
    xintercept = as.numeric(as.Date("2023-07-28")), 
             linetype = "dotted", color = "red")
chart

#Export Chart
ggsave("01_Time Series MAANG.png", chart, path = export.chart,
        dpi = 300, height = 12, width = 23)

Data saham berakhir pada tanggal 28 juli dengan harga saham tertinggi yakni NVIDIA dan daham terendah yakni Amazon. Jika dilihat dari tahun 2019-2022, semua saham cenderung memiliki pola trend naik. Lalu dari 2021-2023 polanya cenderung trend turun. Untuk tugas praktikum kali ini, kami ingin membandingkan pengambilan rentang tahun mana yang lebih baik forcast/peramalannya. Pada Sesi ini hanya akan menggunakan rentang tahun 2022-2023 dengan tren cenderung turun.

Berikut adalah list sesi Rpubs dari rentang tahun yang ada :

1.4.2 Time Series Apple

aapl <- data %>%
  dplyr::select(1, 2, 7) %>%  # Memilih kolom 1, 2, dan 7
  filter(Name == "AAPL", Date >= as.Date("2022-01-01"))  # Filter data saham Amazon tahun 2022 ke atas

rownames(aapl) <- NULL
str(aapl)
## 'data.frame':    394 obs. of  3 variables:
##  $ Name     : chr  "AAPL" "AAPL" "AAPL" "AAPL" ...
##  $ Date     : Date, format: "2022-01-03" "2022-01-04" ...
##  $ Adj Close: num  180 178 173 171 171 ...
datatable(aapl, filter = 'top', 
          options = list(pageLength = 5))

Mengubah Ajd Close Menjadi Time series.

aapl.ts <- ts(aapl[,3])

Ringkasan Data Ajd CLose.

summary(aapl.ts)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   124.7   145.7   156.5   157.9   169.2   195.8
min_value <- min(aapl$`Adj Close`)
min_date <- aapl$Date[which.min(aapl$`Adj Close`)]
percentage <- (which.min(aapl$`Adj Close`) / nrow(aapl)) * 100

chart <-
ggplot(aapl, aes(x=Date, y=`Adj Close`)) + 
  geom_line(aes(color=Name), linewidth=2) +
  scale_color_manual(values = c("lightskyblue4")) +
  labs(x = "\nPeriode (Tahun)", y='Saham Harga penutup',
       title = "Time Series Saham Apple",
       subtitle = "Seperti apa sih pola deret waktu saham Apple?\n") +
  theme(legend.position = "none") +
  theme.ts1 + 
  geom_vline(xintercept = as.numeric(min_date), 
             linetype = "dotted", color = "grey30", linewidth = 1.5) +
  geom_text(aes(x = min_date-1*40, y = max(`Adj Close`)*80/100, label = 
                  paste0("Titik Terendah\n","(",round(percentage, 2), "%)",
                         "   ",min_date)), 
            vjust = -1.5, hjust = 0, size = 7, color = "grey30") 
chart

#Export Chart
ggsave("03_Time Series Apple.png", chart, path = export.chart,
        dpi = 300, height = 12, width = 20)

Berdasarkan grafik deret waktu yang disajikan, terlihat bahwa sekitar \(64.47\%\) dari data menunjukkan kecenderungan musiman yang menurun secara multipel. Kemudian, pada tanggal 2023-01-05, terjadi perubahan pola menjadi tren naik.

Pembagian Data Training Dan Test.

#membagi 80% data latih (training) dan 20% data uji (testing)
train_aapl <- aapl[1: round(nrow(aapl) *80/100),]
test_aapl <- aapl[round(nrow(aapl) *80/100 +1): nrow(aapl),]
train_aapl.ts <- ts(train_aapl[,3])
test_aapl.ts <- ts(train_aapl[,3])

data2 <- data %>%
  dplyr::select(1, 2, 7) %>%  # Memilih kolom 1, 2, dan 7
  filter(Date >= as.Date("2022-01-01")) 
#Banyaknya hari untuk di ramal 
h <- nrow(test_aapl); h
## [1] 79
chart <-
ggplot() + 
  geom_line(data = train_aapl, linewidth=2,
            aes(x = Date, y = `Adj Close`, col = "Data Latih")) +
  geom_line(data = test_aapl, linewidth=2,
            aes(x = Date, y = `Adj Close`, col = "Data Uji")) +
  labs(x = "\nPeriode (Tahun)", y='Saham Harga penutup',
       title = "Time Series Saham Apple",
       subtitle = "Pembagian Data Training dan Test\n") +
  theme(legend.position = "none") +
  scale_colour_manual(name="Keterangan:", 
                      breaks = c("Data Latih", "Data Uji"),
                      values = c("lightskyblue4", "grey30")) + theme.ts1
chart

#Export Chart
ggsave("03_TS_AAPL_train-test.png", chart, path = export.chart,
        dpi = 300, height = 12, width = 20)

Berdasarkan plot data deret waktu pada data latih (\(80\%\) dari data asli), terlihat bahwa data menunjukkan tren turun musiman multiplikatif. Ini mengisyaratkan bahwa data latih tidak memenuhi kriteria stasioneritas dalam rataan maupun ragam. Di sisi lain, dalam plot data uji (\(20\%\) dari data asli), terlihat adanya tren naik dan kurangnya nilai tengah yang stabil. Ini juga menunjukkan bahwa data uji tidak stasioner dalam rataan.

1.4.3 Time Series Amazon

amzn <- data %>%
  dplyr::select(1, 2, 7) %>%  # Memilih kolom 1, 2, dan 7
  filter(Name == "AMZN", Date >= as.Date("2022-01-01"))  # Filter data saham Amazon tahun 2022 ke atas

rownames(amzn) <- NULL
str(amzn)
## 'data.frame':    394 obs. of  3 variables:
##  $ Name     : chr  "AMZN" "AMZN" "AMZN" "AMZN" ...
##  $ Date     : Date, format: "2022-01-03" "2022-01-04" ...
##  $ Adj Close: num  170 168 164 163 163 ...
datatable(amzn, filter = 'top', 
          options = list(pageLength = 5))

Mengubah Ajd Close Menjadi Time series.

amzn.ts <- ts(amzn[,3])

Ringkasan Data Ajd CLose.

summary(amzn.ts)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   81.82  102.01  115.77  119.81  134.88  170.40
min_value <- min(amzn$`Adj Close`)
min_date <- amzn$Date[which.min(amzn$`Adj Close`)]
percentage <- (which.min(amzn$`Adj Close`) / nrow(amzn)) * 100

chart <-
ggplot(amzn, aes(x=Date, y=`Adj Close`)) + 
  geom_line(aes(color=Name), linewidth=2) +
  scale_color_manual(values = c("orange2")) +
  labs(x = "\nPeriode (Tahun)", y='Saham Harga penutup',
       title = "Time Series Saham Amazon",
       subtitle = "Seperti apa sih pola deret waktu saham Amazon?\n") +
  theme(legend.position = "none") +
  theme.ts1 + 
  geom_vline(xintercept = as.numeric(min_date), 
             linetype = "dotted", color = "grey30", linewidth = 1.5) +
  geom_text(aes(x = min_date-1*40, y = max(`Adj Close`)*80/100, label = 
                  paste0("Titik Potong\n","(",round(percentage, 2), "%)",
                         "   ",min_date)), 
            vjust = -1.5, hjust = 0, size = 7, color = "grey30") 
chart

#Export Chart
ggsave("02_Time Series Amazon.png", chart, path = export.chart,
        dpi = 300, height = 12, width = 20)

Dari grafik deret waktu yang ditampilkan, terlihat bahwa sekitar \(63.2\%\) dari data menunjukkan kecenderungan musiman yang menurun secara aditif. Selanjutnya, pada tanggal 2022-12-28, terjadi perubahan pola menjadi tren naik.

Pembagian Data Training Dan Test.

#membagi 80% data latih (training) dan 20% data uji (testing)
train_amzn <- amzn[1: round(nrow(amzn) *80/100),]
test_amzn <- amzn[round(nrow(amzn) *80/100 +1): nrow(amzn),]
train_amzn.ts <- ts(train_amzn[,3])
test_amzn.ts <- ts(test_amzn[,3])
chart <-
ggplot() + 
  geom_line(data = train_amzn, linewidth=2,
            aes(x = Date, y = `Adj Close`, col = "Data Latih")) +
  geom_line(data = test_amzn, linewidth=2,
            aes(x = Date, y = `Adj Close`, col = "Data Uji")) +
  labs(x = "\nPeriode (Tahun)", y='Saham Harga penutup',
       title = "Time Series Saham Amazon",
       subtitle = "Pembagian Data Training dan Test\n") +
  theme(legend.position = "none") +
  scale_colour_manual(name="Keterangan:", 
                      breaks = c("Data Latih", "Data Uji"),
                      values = c("orange", "grey30")) + theme.ts1
chart

#Export Chart
ggsave("02_TS_Amazon_train-test.png", chart, path = export.chart,
        dpi = 300, height = 12, width = 20)

Dari plot deret waktu data latih (\(80\%\) dari data asli), terlihat bahwa data menunjukkan tren turun musiman secara aditif. Ini menunjukkan ketidakstabilan dalam nilai tengah dan variabilitas data latih, yang tidak memenuhi kriteria stasioneritas dalam rataan maupun ragam. Di sisi lain, dalam plot data uji (\(20\%\) dari data asli), terlihat adanya tren naik dan absennya nilai tengah yang stabil. Hal ini juga mengindikasikan bahwa data uji tidak memenuhi kriteria stasioneritas dalam rataan.

1.4.4 Time Series Google

goog <- data %>%
  dplyr::select(1, 2, 7) %>%  # Memilih kolom 1, 2, dan 7
  filter(Name == "GOOG", Date >= as.Date("2022-01-01"))  # Filter data saham Amazon tahun 2022 ke atas

rownames(goog) <- NULL
str(goog)
## 'data.frame':    394 obs. of  3 variables:
##  $ Name     : chr  "GOOG" "GOOG" "GOOG" "GOOG" ...
##  $ Date     : Date, format: "2022-01-03" "2022-01-04" ...
##  $ Adj Close: num  145 144 138 138 137 ...
datatable(goog, filter = 'top', 
          options = list(pageLength = 5))

Mengubah Ajd Close Menjadi Time series.

goog.ts <- ts(goog[,3])

Ringkasan Data Ajd CLose.

summary(goog.ts)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   83.49  100.08  112.11  112.73  123.48  148.04
min_value <- min(goog$`Adj Close`)
min_date <- goog$Date[which.min(goog$`Adj Close`)]
percentage <- (which.min(goog$`Adj Close`) / nrow(goog)) * 100

chart <-
ggplot(goog, aes(x=Date, y=`Adj Close`)) + 
  geom_line(aes(color=Name), linewidth=2) +
  scale_color_manual(values = c("gold3")) +
  labs(x = "\nPeriode (Tahun)", y='Saham Harga penutup',
       title = "Time Series Saham Google",
       subtitle = "Seperti apa sih pola deret waktu saham Google?\n") +
  theme(legend.position = "none") +
  theme.ts1 + 
  geom_vline(xintercept = as.numeric(min_date), 
             linetype = "dotted", color = "grey30", linewidth = 1.5) +
  geom_text(aes(x = min_date-1*40, y = max(`Adj Close`)*80/100, label = 
                  paste0("Titik Terendah\n","(",round(percentage, 2), "%)",
                         "   ",min_date)), 
            vjust = -1.5, hjust = 0, size = 7, color = "grey30") 
chart

#Export Chart
ggsave("04_Time Series Google.png", chart, path = export.chart,
        dpi = 300, height = 12, width = 20)

Melalui visualisasi grafik deret waktu yang disuguhkan, tampaknya sekitar \(53.81\%\) data menggambarkan tren menurun. Lalu, pada tanggal 2021-11-03, terjadi perubahan pola menjadi tren naik.

Pembagian Data Training Dan Test.

#membagi 80% data latih (training) dan 20% data uji (testing)
train_goog <- goog[1: round(nrow(goog) *80/100),]
test_goog <- goog[round(nrow(goog) *80/100 +1): nrow(goog),]
train_goog.ts <- ts(train_goog[,3])
test_goog.ts <- ts(test_goog[,3])
chart <-
ggplot() + 
  geom_line(data = train_goog, linewidth=2,
            aes(x = Date, y = `Adj Close`, col = "Data Latih")) +
  geom_line(data = test_goog, linewidth=2,
            aes(x = Date, y = `Adj Close`, col = "Data Uji")) +
  labs(x = "\nPeriode (Tahun)", y='Saham Harga penutup',
       title = "Time Series Saham Google",
       subtitle = "Pembagian Data Training dan Test\n") +
  theme(legend.position = "none") +
  scale_colour_manual(name="Keterangan:", 
                      breaks = c("Data Latih", "Data Uji"),
                      values = c("gold3", "grey30")) + theme.ts1
chart

#Export Chart
ggsave("04_TS_GOOG_train-test.png", chart, path = export.chart,
        dpi = 300, height = 12, width = 20)

Melalui plot deret waktu dari data latih (\(80\%\) dari data asli), terlihat bahwa data menggambarkan tren menurun yang cukup jelas. Hal ini menunjukkan bahwa data latih tidak menunjukkan sifat stasioneritas dalam rataan. Sementara itu, dalam plot data uji (\(20\%\) dari data asli), tampaknya terdapat tren naik yang signifikan, dan tidak ada nilai tengah yang tetap. Ini juga mengindikasikan bahwa data uji tidak memenuhi kriteria stasioneritas dalam rataan.

1.4.5 Time Series META

meta <- data %>%
  dplyr::select(1, 2, 7) %>%  # Memilih kolom 1, 2, dan 7
  filter(Name == "META", Date >= as.Date("2022-01-01"))  # Filter data saham Amazon tahun 2022 ke atas

rownames(meta) <- NULL
str(meta)
## 'data.frame':    394 obs. of  3 variables:
##  $ Name     : chr  "META" "META" "META" "META" ...
##  $ Date     : Date, format: "2022-01-03" "2022-01-04" ...
##  $ Adj Close: num  339 337 324 332 332 ...
datatable(meta, filter = 'top', 
          options = list(pageLength = 5))

Mengubah Ajd Close Menjadi Time series.

meta.ts <- ts(meta[,3])

Ringkasan Data Ajd CLose.

summary(meta.ts)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   88.91  156.15  187.84  195.00  223.21  338.54
min_value <- min(meta$`Adj Close`)
min_date <- meta$Date[which.min(meta$`Adj Close`)]
percentage <- (which.min(meta$`Adj Close`) / nrow(meta)) * 100

chart <-
ggplot(meta, aes(x=Date, y=`Adj Close`)) + 
  geom_line(aes(color=Name), linewidth=2) +
  scale_color_manual(values = c("dodgerblue3")) +
  labs(x = "\nPeriode (Tahun)", y='Saham Harga penutup',
       title = "Time Series Saham META",
       subtitle = "Seperti apa sih pola deret waktu saham META?\n") +
  theme(legend.position = "none") +
  theme.ts1 + 
  geom_vline(xintercept = as.numeric(min_date), 
             linetype = "dotted", color = "grey30", linewidth = 1.5) +
  geom_text(aes(x = min_date-1*40, y = max(`Adj Close`)*80/100, label = 
                  paste0("Titik Terendah\n","(",round(percentage, 2), "%)",
                         "   ",min_date)), 
            vjust = -1.5, hjust = 0, size = 7, color = "grey30") 
chart

#Export Chart
ggsave("05_Time Series META.png", chart, path = export.chart,
        dpi = 300, height = 12, width = 20)

Melalui grafik deret waktu yang disajikan, terlihat bahwa sekitar \(53.81\%\) dari data menunjukkan kecenderungan penurunan tren. Lalu, pada tanggal 2022-11-03, terjadi perubahan pola menjadi tren naik. Pola perubahan ini, beserta tanggal dan persentasenya, serupa dengan yang terlihat dalam pergerakan saham Google.

Pembagian Data Training Dan Test2

#membagi 80% data latih (training) dan 20% data uji (testing)
train_meta <- meta[1: round(nrow(meta) *80/100),]
test_meta <- meta[round(nrow(meta) *80/100 +1): nrow(meta),]
train_meta.ts <- ts(train_meta[,3])
test_meta.ts <- ts(test_meta[,3])
chart <-
ggplot() + 
  geom_line(data = train_meta, linewidth=2,
            aes(x = Date, y = `Adj Close`, col = "Data Latih")) +
  geom_line(data = test_meta, linewidth=2,
            aes(x = Date, y = `Adj Close`, col = "Data Uji")) +
  labs(x = "\nPeriode (Tahun)", y='Saham Harga penutup',
       title = "Time Series Saham META",
       subtitle = "Pembagian Data Training dan Test\n") +
  theme(legend.position = "none") +
  scale_colour_manual(name="Keterangan:", 
                      breaks = c("Data Latih", "Data Uji"),
                      values = c("dodgerblue3", "grey30")) + theme.ts1
chart

#Export Chart
ggsave("05_TS_META_train-test.png", chart, path = export.chart,
        dpi = 300, height = 12, width = 20)

Berdasarkan grafik deret waktu data latih (\(80\%\) dari data asli), tampak bahwa data menunjukkan kombinasi tren turun dan tren naik. Hal ini menunjukkan bahwa data latih tidak memenuhi syarat stasioneritas dalam rataan maupun ragam. Sementara itu, pada plot data uji (\(20\%\) dari data asli), terlihat tren naik yang signifikan dan ketiadaan nilai tengah yang konsisten. Ini juga menandakan bahwa data uji tidak memenuhi syarat stasioneritas dalam rataan.

1.4.6 Time Series Microsoft

msft <- data %>%
  dplyr::select(1, 2, 7) %>%  # Memilih kolom 1, 2, dan 7
  filter(Name == "MSFT", Date >= as.Date("2022-01-01"))  # Filter data saham Amazon tahun 2022 ke atas

rownames(msft) <- NULL
str(msft)
## 'data.frame':    394 obs. of  3 variables:
##  $ Name     : chr  "MSFT" "MSFT" "MSFT" "MSFT" ...
##  $ Date     : Date, format: "2022-01-03" "2022-01-04" ...
##  $ Adj Close: num  330 324 312 310 310 ...
datatable(msft, filter = 'top', 
          options = list(pageLength = 5))

Mengubah Ajd Close Menjadi Time series.

msft.ts <- ts(msft[,3])

Ringkasan Data Ajd CLose.

summary(msft.ts)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   212.6   249.5   271.8   275.4   296.7   359.5
min_value <- min(msft$`Adj Close`)
min_date <- msft$Date[which.min(msft$`Adj Close`)]
percentage <- (which.min(msft$`Adj Close`) / nrow(msft)) * 100

chart <-
ggplot(msft, aes(x=Date, y=`Adj Close`)) + 
  geom_line(aes(color=Name), linewidth=2) +
  scale_color_manual(values = c("deepskyblue2")) +
  labs(x = "\nPeriode (Tahun)", y='Saham Harga penutup',
       title = "Time Series Saham Microsoft",
       subtitle = "Seperti apa sih pola deret waktu saham Microsoft?\n") +
  theme(legend.position = "none") +
  theme.ts1 + 
  geom_vline(xintercept = as.numeric(min_date), 
             linetype = "dotted", color = "grey30", linewidth = 1.5) +
  geom_text(aes(x = min_date-1*40, y = max(`Adj Close`)*80/100, label = 
                  paste0("Titik Terendah\n","(",round(percentage, 2), "%)",
                         "   ",min_date)), 
            vjust = -1.5, hjust = 0, size = 7, color = "grey30") 
chart

#Export Chart
ggsave("06_Time Series Microsoft.png", chart, path = export.chart,
        dpi = 300, height = 12, width = 20)

Dalam gambaran grafik deret waktu yang diberikan, sekitar $53.81%$ data menunjukkan adanya tren penurunan yang tampak. Lalu, pada tanggal 2022-11-03, terjadi perubahan pola menjadi tren kenaikan. Karakteristik tanggal dan persentase perubahan pola ini serupa dengan yang dapat ditemukan pada pergerakan saham Google dan META.

Pembagian Data Training Dan Test.

#membagi 80% data latih (training) dan 20% data uji (testing)
train_msft <- msft[1: round(nrow(msft) *80/100),]
test_msft <- msft[round(nrow(msft) *80/100 +1): nrow(msft),]
train_msft.ts <- ts(train_msft[,3])
test_msft.ts <- ts(test_msft[,3])
chart <-
ggplot() + 
  geom_line(data = train_msft, linewidth=2,
            aes(x = Date, y = `Adj Close`, col = "Data Latih")) +
  geom_line(data = test_msft, linewidth=2,
            aes(x = Date, y = `Adj Close`, col = "Data Uji")) +
  labs(x = "\nPeriode (Tahun)", y='Saham Harga penutup',
       title = "Time Series Saham Microsoft",
       subtitle = "Pembagian Data Training dan Test\n") +
  theme(legend.position = "none") +
  scale_colour_manual(name="Keterangan:", 
                      breaks = c("Data Latih", "Data Uji"),
                      values = c("deepskyblue2", "grey30")) + theme.ts1
chart

#Export Chart
ggsave("06_TS_MSFT_train-test.png", chart, path = export.chart,
        dpi = 300, height = 12, width = 20)

Dari visualisasi grafik deret waktu pada data latih (\(80\%\) dari data asli), terlihat bahwa data menunjukkan adanya tren turun dan tren naik. Hal ini menunjukkan bahwa data latih tidak memenuhi kriteria stasioneritas dalam rataan maupun ragam. Sementara itu, dalam plot data uji (\(20\%\) dari data asli), tampaknya terdapat tren kenaikan yang signifikan dan ketiadaan nilai tengah yang stabil. Hal ini juga menandakan bahwa data uji tidak memenuhi persyaratan stasioneritas dalam rataan.

1.4.7 Time Series Netflix

nflx <- data %>%
  dplyr::select(1, 2, 7) %>%  # Memilih kolom 1, 2, dan 7
  filter(Name == "NFLX", Date >= as.Date("2022-01-01"))  # Filter data saham Amazon tahun 2022 ke atas

rownames(nflx) <- NULL
str(nflx)
## 'data.frame':    394 obs. of  3 variables:
##  $ Name     : chr  "NFLX" "NFLX" "NFLX" "NFLX" ...
##  $ Date     : Date, format: "2022-01-03" "2022-01-04" ...
##  $ Adj Close: num  597 591 568 553 541 ...
datatable(nflx, filter = 'top', 
          options = list(pageLength = 5))

Mengubah Ajd Close Menjadi Time series.

nflx.ts <- ts(nflx[,3])

Ringkasan Data Ajd CLose.

summary(nflx.ts)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   166.4   232.8   317.7   312.6   367.8   597.4
min_value <- min(nflx$`Adj Close`)
min_date <- nflx$Date[which.min(nflx$`Adj Close`)]
percentage <- (which.min(nflx$`Adj Close`) / nrow(nflx)) * 100

chart <-
ggplot(nflx, aes(x=Date, y=`Adj Close`)) + 
  geom_line(aes(color=Name), linewidth=2) +
  scale_color_manual(values = c("firebrick3")) +
  labs(x = "\nPeriode (Tahun)", y='Saham Harga penutup',
       title = "Time Series Saham Netflix",
       subtitle = "Seperti apa sih pola deret waktu saham Netflix?\n") +
  theme(legend.position = "none") +
  theme.ts1 + 
  geom_vline(xintercept = as.numeric(min_date), 
             linetype = "dotted", color = "grey30", linewidth = 1.5) +
  geom_text(aes(x = min_date-1*40, y = max(`Adj Close`)*80/100, label = 
                  paste0("Titik Terendah\n","(",round(percentage, 2), "%)",
                         "   ",min_date)), 
            vjust = -1.5, hjust = 0, size = 7, color = "grey30") 
chart

#Export Chart
ggsave("07_Time Series Netflix.png", chart, path = export.chart,
        dpi = 300, height = 12, width = 20)

Berbeda dari yang lain, berdasarkan grafik deret waktu yang disajikan, terlihat bahwa sekitar \(22.84\%\) dari data menunjukkan kecenderungan tren menurun. Kemudian, pada tanggal 2022-05-11, terjadi perubahan pola menjadi tren naik.

Pembagian Data Training Dan Test.

#membagi 80% data latih (training) dan 20% data uji (testing)
train_nflx <- nflx[1: round(nrow(nflx) *80/100),]
test_nflx <- nflx[round(nrow(nflx) *80/100  +1): nrow(nflx),]
train_nflx.ts <- ts(train_nflx[,3])
test_nflx.ts <- ts(test_nflx[,3])
chart <-
ggplot() + 
  geom_line(data = train_nflx, linewidth=2,
            aes(x = Date, y = `Adj Close`, col = "Data Latih")) +
  geom_line(data = test_nflx, linewidth=2,
            aes(x = Date, y = `Adj Close`, col = "Data Uji")) +
  labs(x = "\nPeriode (Tahun)", y='Saham Harga penutup',
       title = "Time Series Saham Netflix",
       subtitle = "Pembagian Data Training dan Test\n") +
  theme(legend.position = "none") +
  scale_colour_manual(name="Keterangan:", 
                      breaks = c("Data Latih", "Data Uji"),
                      values = c("firebrick3", "grey30")) + theme.ts1
chart

#Export Chart
ggsave("07_TS_NFLX_train-test.png", chart, path = export.chart,
        dpi = 300, height = 12, width = 20)

Berdasarkan plot data deret waktu pada data latih (\(80\%\) dari data asli), terlihat bahwa data menunjukkan tren turun yang drastis dan tren naik yang cukup mulus. Ini mengisyaratkan bahwa data latih tidak memenuhi kriteria stasioneritas dalam rataan maupun ragam. Di sisi lain, dalam plot data uji (\(20\%\) dari data asli), terlihat adanya tren naik dan kurangnya nilai tengah yang stabil. Ini juga menunjukkan bahwa data uji tidak stasioner dalam rataan.

1.4.8 Time Series NVIDIA

nvda <- data %>%
  dplyr::select(1, 2, 7) %>%  # Memilih kolom 1, 2, dan 7
  filter(Name == "NVDA", Date >= as.Date("2022-01-01"))  # Filter data saham Amazon tahun 2022 ke atas

rownames(nvda) <- NULL
str(nvda)
## 'data.frame':    394 obs. of  3 variables:
##  $ Name     : chr  "NVDA" "NVDA" "NVDA" "NVDA" ...
##  $ Date     : Date, format: "2022-01-03" "2022-01-04" ...
##  $ Adj Close: num  301 293 276 281 272 ...
datatable(nvda, filter = 'top', 
          options = list(pageLength = 5))

Mengubah Ajd Close Menjadi Time series.

nvda.ts <- ts(nvda[,3])

Ringkasan Data Ajd CLose.

summary(nvda.ts)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   112.2   162.5   207.0   226.0   267.4   474.9
min_value <- min(nvda$`Adj Close`)
min_date <- nvda$Date[which.min(nvda$`Adj Close`)]
percentage <- (which.min(nvda$`Adj Close`) / nrow(nvda)) * 100

chart <-
ggplot(nvda, aes(x=Date, y=`Adj Close`)) + 
  geom_line(aes(color=Name), linewidth=2) +
  scale_color_manual(values = c("green4")) +
  labs(x = "\nPeriode (Tahun)", y='Saham Harga penutup',
       title = "Time Series Saham NVIDIA",
       subtitle = "Seperti apa sih pola deret waktu saham NVIDIA?\n") +
  theme(legend.position = "none") +
  theme.ts1 + 
  geom_vline(xintercept = as.numeric(min_date), 
             linetype = "dotted", color = "grey30", linewidth = 1.5) +
  geom_text(aes(x = min_date-1*40, y = max(`Adj Close`)*80/100, label = 
                  paste0("Titik Terendah\n","(",round(percentage, 2), "%)",
                         "   ",min_date)), 
            vjust = -1.5, hjust = 0, size = 7, color = "grey30") 
chart

#Export Chart
ggsave("08_Time Series NVIDIA.png", chart, path = export.chart,
        dpi = 300, height = 12, width = 20)

Berdasarkan grafik deret waktu yang disajikan, terlihat bahwa sekitar \(50.25\%\) dari data menunjukkan kecenderungan tren menurun. Kemudian, pada tanggal 2022-10-14, terjadi perubahan pola menjadi tren naik dan menaik tajam pada Juli 2023.

Pembagian Data Training Dan Test.

#membagi 80% data latih (training) dan 20% data uji (testing)
train_nvda <- nvda[1: round(nrow(nvda) *80/100),]
test_nvda <- nvda[round(nrow(nvda) *80/100 +1): nrow(nvda),]
train_nvda.ts <- ts(train_nvda[,3])
test_nvda.ts <- ts(test_nvda[,3])
chart <-
ggplot() + 
  geom_line(data = train_nvda, linewidth=2,
            aes(x = Date, y = `Adj Close`, col = "Data Latih")) +
  geom_line(data = test_nvda, linewidth=2,
            aes(x = Date, y = `Adj Close`, col = "Data Uji")) +
  labs(x = "\nPeriode (Tahun)", y='Saham Harga penutup',
       title = "Time Series Saham NVIDIA",
       subtitle = "Pembagian Data Training dan Test\n") +
  theme(legend.position = "none") +
  scale_colour_manual(name="Keterangan:", 
                      breaks = c("Data Latih", "Data Uji"),
                      values = c("green4", "grey30")) + theme.ts1
chart

#Export Chart
ggsave("08_TS_NVDA_train-test.png", chart, path = export.chart,
        dpi = 300, height = 12, width = 20)

Berdasarkan plot data deret waktu pada data latih (\(80\%\) dari data asli), terlihat bahwa data menunjukkan tren turun dan tren naik yang keduanya mulus. Ini mengisyaratkan bahwa data latih tidak memenuhi kriteria stasioneritas dalam rataan maupun ragam. Di sisi lain, dalam plot data uji (\(20\%\) dari data asli), terlihat adanya tren yang melonjak naik dan kurangnya nilai tengah yang stabil. Ini juga menunjukkan bahwa data uji tidak stasioner dalam rataan.

2 Apple

2.1 Uji Stasioner Data

install_load('tsibble','tseries')

2.1.1 Plot ACF

acf(train_aapl.ts)

Berdasarkan plot ACF, terlihat bahwa plot ACF data train menurun secara perlahan (tails of slowly). Hal ini juga menjadi indikasi bahwa data tidak stasioner dalam rataan dan tidak membentuk gelombang sinus.

2.1.2 Uji ADF

tseries::adf.test(train_aapl.ts)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  train_aapl.ts
## Dickey-Fuller = -2.2316, Lag order = 6, p-value = 0.4788
## alternative hypothesis: stationary

\(H_0\) : Data tidak stasioner dalam rataan

\(H_1\) : Data stasioner dalam rataan

Berdasarkan uji ADF tersebut, didapat p-value sebesar \(0.4788\) yang lebih besar dari taraf nyata \(5\%\) sehingga tak tolak \(H_0\) dan menandakan bahwa data tidak stasioner dalam rataan. Hal ini sesuai dengan hasil eksplorasi menggunakan plot time series dan plot ACF, sehingga ketidakstasioneran model kedepannya harus ditangani.

2.1.3 Plot Box-Cox

install_load('MASS')
index <- seq(1:nrow(aapl))
bc = boxcox(aapl.ts~index, lambda = seq(-2, 4, by=0.01))

#Nilai Rounded Lambda
lambda_aapl <- bc$x[which.max(bc$y)]
#SK
sk_aapl <- bc$x[bc$y > max(bc$y) - 1/2 * qchisq(.95,1)]
cat(" Lambda :", lambda_aapl,
    "\n\n Selang Kepercyaan 95% \n",
    "Batas Bawah :", min(sk_aapl), "\n Batas Atas  :", max(sk_aapl) )
##  Lambda : 0.06 
## 
##  Selang Kepercyaan 95% 
##  Batas Bawah : -0.88 
##  Batas Atas  : 0.99

Gambar di atas menunjukkan nilai rounded value (\(\lambda\)) optimum sebesar \(0.06\) dan pada selang kepercayaan \(95\%\) nilai memiliki batas bawah \(-0.88\) dan batas atas \(0.99\). Selang tersebut tidak memuat nilai satu (walaupun hampir) sehingga dapat dikatakan bahwa data saham Apple tidak stasioner dalam ragam.

2.1.4 Penanganan Ketidakstasioneran Data

train_aapl.diff <- diff(train_aapl.ts, differences = 1) 
plot.ts(train_aapl.diff, lty=1, xlab="Periode (Tahun)", 
        col = "lightskyblue4", lwd = 3.5,
        main="Plot Difference Saham Apple")

Berdasarkan plot data deret waktu, terlihat bahwa data sudah stasioner dalam rataan ditandai dengan data bergerak pada nilai tengah tertentu (tidak terdapat trend ataupun musiman pada data).

2.2 Uji Ulang

2.2.1 Plot ACF

acf(train_aapl.diff)

Berdasarkan plot tersebut, terlihat bahwa plot ACF cuts off pada lag ke 0. Hal ini menandakan data sudah stasioner dalam rataan dan ketidakstasioneran data telah berhasil tertangani.

2.2.2 Uji ADF

tseries::adf.test(train_aapl.diff)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  train_aapl.diff
## Dickey-Fuller = -6.335, Lag order = 6, p-value = 0.01
## alternative hypothesis: stationary

\(H_0\) : Data tidak stasioner dalam rataan

\(H_1\) : Data stasioner dalam rataan

Berdasarkan uji ADF tersebut, didapat p-value sebesar \(0.01\) yang lebih kecil dari taraf nyata \(5\%\) sehingga tolak \(H_0\) atau data stasioner dalam rataan. Hal ini sesuai dengan hasil eksplorasi menggunakan plot time series dan plot ACF, sehingga dalam hal ini ketidakstasioneran data sudah berhasil ditangani dan dapat dilanjutkan ke pemodelan.

2.3 Identifikasi Model

2.3.1 Plot ACF

acf(train_aapl.diff)

Berdasarkan plot tersebut, terlihat bahwa plot ACF cuts off pada lag ke 0. Sehingga model tidak dapat di identifikasi dengan plot ACF.

2.3.2 Plot PACF

pacf(train_aapl.diff)

Berdasarkan plot PACF tersebut, terlihat bahwa tidak ada satupun lag yang cut off. Maka model tidak dapat di identifikasi dengan plot PACF.

2.3.3 Plot EACF

install_load('TSA')
eacf(train_aapl.diff)
## AR/MA
##   0 1 2 3 4 5 6 7 8 9 10 11 12 13
## 0 o o o o o o o o o o o  o  o  o 
## 1 x o o o o o o o o o o  o  o  o 
## 2 x x o o o o o o o o o  o  o  o 
## 3 x o x o o o o o o o o  o  o  o 
## 4 x x x x o o o o o o o  o  o  o 
## 5 o x x x x o o o o o o  o  o  o 
## 6 x o x x x o o o o o o  o  o  o 
## 7 x o x o x x x o o o o  o  o  o

Identifikasi model menggunakan plot EACF dilakukan dengan melihat titik sudut kiri segitiga pada pola segitiga nol atas (pola mariks segitiga bawah). Sebagai contoh :

Dalam hal ini model tentatif yang terbentuk adalah ARIMA(0,1,1), ARIMA(1,1,1), ARIMA(2,1,2), ARIMA(3,1,3), dst.. Namun karena kemungkinannya sangat banyak, maka akan digunakan function agar menyingkat proses.

2.4 Pendugaan Parameter Model Tentatif

Untuk menduga parameter model tentatif, kami akan menggunakan function berdasarkan plot EACF yang sudah dirancang sebagai berikut.

Keterangan parameter function :

  • data = data Time Series baik yang sudah di .diff maupun belum

  • p_max = ordo maksimal dari AR

  • d = ordo I

  • q_max = ordo maksimal dari MA

  • alpha = alpha

install_load('forecast')

# Fungsi untuk menghitung model ARIMA dan menganalisis parameter
model_tentatif <- function(data, p_max, d, q_max, alpha=0.05) {
  best_model <- NULL
  best_aic <- Inf
  eacf_result <- eacf(data)
  models <- data.frame(Model = character(0), 
                       AIC = numeric(0), 
                       Signif = character(0), 
                       Keterangan = character(0))
  
  for (p in 0:p_max) {
    for (q in 1:q_max) {
      #Pola Matriks segitiga bawah
      if (!is.na(eacf_result$symbol[p + 1, q + 1]) && 
          !is.na(eacf_result$symbol[p + 1, q + 2]) && 
          !is.na(eacf_result$symbol[p + 2, q + 2])) {
        if (eacf_result$symbol[p + 1, q + 1] == "o" && 
            eacf_result$symbol[p + 1, q + 2] == "o" && 
            eacf_result$symbol[p + 2, q + 2] == "o") {
      
          model <- Arima(data, order = c(p, d, q), method = "ML")
          aic <- AIC(model)
          
          # Mendapatkan nilai coef dari model
          coeftest_result <- lmtest::coeftest(model)
          
          # jika lebih kecil dari alpha, maka signifikan
          significant_params <- 
            rownames(coeftest_result)[coeftest_result[, "Pr(>|z|)"] < alpha]  
          
          # jika lebih besar dari alpha, maka tidak signifikan
          non_significant_params <- 
            rownames(coeftest_result)[coeftest_result[, "Pr(>|z|)"] > alpha]  
          
          # Keterangan signifikansi
          if (length(significant_params) == 0) {
            keterangan <- "Semua parameter tidak signifikan"
          } else if (length(significant_params) == nrow(coeftest_result)) {
            keterangan <- "Semua parameter signifikan"
          } else {
            keterangan <- paste("Parameter yang tidak signifikan adalah", 
                                paste(non_significant_params, collapse = ", "))
          }
          
          models <- rbind(models, 
                    data.frame(Model = paste("ARIMA(", p, ",", d, ",", q, ")", 
                                             sep = ""), 
                               AIC = aic, 
                               Signif = paste(significant_params, 
                                              collapse = ", "), 
                               Keterangan = keterangan))
          
          #Identifikasi Best Model
            if (keterangan == "Semua parameter signifikan" && 
                !any(is.na(significant_params))) {
              if (aic < best_aic) {
                best_model <- model
                best_aic <- aic
            }
          }
        }
      }
    }
  }
  
  cat("\nModel ARIMA dengan AIC terkecil:\n")
  print(best_model)

  return(models)
}

# Panggil Fungsi
model.tentaif_aapl <- 
  model_tentatif(train_aapl.diff, p_max = 6, d = 1, q_max = 12)
## AR/MA
##   0 1 2 3 4 5 6 7 8 9 10 11 12 13
## 0 o o o o o o o o o o o  o  o  o 
## 1 x o o o o o o o o o o  o  o  o 
## 2 x x o o o o o o o o o  o  o  o 
## 3 x o x o o o o o o o o  o  o  o 
## 4 x x x x o o o o o o o  o  o  o 
## 5 o x x x x o o o o o o  o  o  o 
## 6 x o x x x o o o o o o  o  o  o 
## 7 x o x o x x x o o o o  o  o  o 
## 
## Model ARIMA dengan AIC terkecil:
## Series: data 
## ARIMA(0,1,1) 
## 
## Coefficients:
##           ma1
##       -1.0000
## s.e.   0.0496
## 
## sigma^2 = 10.24:  log likelihood = -810.5
## AIC=1624.99   AICc=1625.03   BIC=1632.49
datatable(model.tentaif_aapl, filter = 'top', 
          options = list(pageLength = 5))

Berdasarkan pendugaan parameter di atas, nilai AIC terkecil \(1624.99\) dimiliki oleh model ARIMA(0,1,1) dan seluruh parameternya signifikan sehingga model yang dipilih adalah model ARIMA(0,1,1) .

model_aapl.da <- Arima(train_aapl.diff, order=c(0,1,1), method="ML")

2.5 Analisis Sisaan

Model terbaik hasil identifikasi kemudian dicek asumsi sisaannya. Sisaan model ARIMA harus memenuhi asumsi normalitas, kebebasan sisaan, dan kehomogenan ragam. Diagnostik model dilakukan secara eksplorasi dan uji formal.

2.5.1 Eksplorasi Sisaan

#Eksplorasi 
sisaan_aapl.da <- model_aapl.da$residuals 
par(mfrow=c(2,2)) 
# QQ-Plot
qqnorm(sisaan_aapl.da) 
qqline(sisaan_aapl.da, col = "dodgerblue3", lwd = 2.5) 
# Plot sisaan
plot(c(1:length(sisaan_aapl.da)), sisaan_aapl.da, 
     main = "Plot Sisaan Model ARIMA",
     xlab = "Periode",
     ylab = "Nilai Sisaan")
abline(h = 0, col = "firebrick2", lty = 2, lwd=2.5)
#Plot ACF dan PACF
acf(sisaan_aapl.da) 
pacf(sisaan_aapl.da) 

Berdasarkan plot kuantil-kuantil normal, secara eksplorasi ditunjukkan sisaan menyebar normal ditandai dengan tititk-titiknya cenderung mengikuti garis \(45^{\circ}\). Kemudian dapat dilihat juga lebar pita sisaan yang cenderung sama menandakan bahwa sisaan memiliki ragam yang homogen. Plot ACF dan PACF sisaan ARIMA(0,1,1) juga tidak signifikan pada 20 lag awal yang menandakan saling bebas. Kondisi ini akan diuji lebih lanjut dengan uji formal.

2.5.2 Uji Formal

2.5.2.1 Sisaan Menyebar Normal

ks.test(sisaan_aapl.da,"pnorm")  #tak tolak H0 > sisaan menyebar normal
## 
##  Asymptotic one-sample Kolmogorov-Smirnov test
## 
## data:  sisaan_aapl.da
## D = 0.28445, p-value < 2.2e-16
## alternative hypothesis: two-sided

Selain dengan eksplorasi, asumsi tersebut dapat diuji menggunakan uji formal. Pada tahapan ini uji formal yang digunakan untuk normalitas adalah uji Kolmogorov-Smirnov (KS). Hipotesis pada uji KS adalah sebagai berikut.

\(H_0\) : Sisaan menyebar normal

\(H_1\) : Sisaan tidak menyebar normal

Berdasarkan uji KS tersebut, didapat p-value sebesar \(2.2\times10^{-16}\) yang kurang dari taraf nyata \(5\%\) sehingga tolak \(H_0\) dan menandakan bahwa sisaan tidak menyebar normal.

2.5.2.2 Sisaan saling bebas

Box.test(sisaan_aapl.da, type = "Ljung")  #tak tolak H0 > sisaan saling bebas
## 
##  Box-Ljung test
## 
## data:  sisaan_aapl.da
## X-squared = 0.074032, df = 1, p-value = 0.7856

Selanjutnya akan dilakukan uji formal untuk kebebasan sisaan menggunakan uji Ljung-Box. Hipotesis yang digunakan adalah sebagai berikut.

\(H_0\) : Sisaan saling bebas

\(H_1\) : Sisaan tidak tidak saling bebas

Berdasarkan uji Ljung-Box tersebut, didapat p-value sebesar \(0.7856\) yang lebih besar dari taraf nyata \(5\%\) sehingga tak tolak \(H_0\) dan menandakan bahwa sisaan saling bebas. Yang berarti tidak ada autokorelasi. Hal ini sesuai dengan hasil eksplorasi menggunakan plot ACF dan PACF.

2.5.2.3 Sisaan homogen

Box.test((sisaan_aapl.da)^2, type = "Ljung")  #tak tolak H0 > sisaan homogen
## 
##  Box-Ljung test
## 
## data:  (sisaan_aapl.da)^2
## X-squared = 1.358, df = 1, p-value = 0.2439

Hipotesis yang digunakan untuk uji kehomogenan ragam adalah sebagai berikut.

\(H_0\) : Ragam sisaan homogen

\(H_1\) : Ragam sisaan tidak homogen

Berdasarkan uji Ljung-Box terhadap sisaan kuadrat tersebut, didapat p-value sebesar \(0.2439\) yang lebih besar dari taraf nyata \(5\%\) sehingga tak tolak \(H_0\) dan menandakan bahwa ragam sisaan homogen.

2.5.2.4 Nilai tengah sama dengan nol

#4) Nilai tengah sisaan sama dengan nol 
t.test(sisaan_aapl.da, mu = 0, conf.level = 0.95)  #tak tolak h0 > nilai tengah sisaan sama dengan 0
## 
##  One Sample t-test
## 
## data:  sisaan_aapl.da
## t = 1.4112, df = 313, p-value = 0.1592
## alternative hypothesis: true mean is not equal to 0
## 95 percent confidence interval:
##  -0.09998067  0.60711914
## sample estimates:
## mean of x 
## 0.2535692

Terakhir, dengan uji-t, akan dicek apakah nilai tengah sisaan sama dengan nol. Hipotesis yang diujikan sebagai berikut.

\(H_0\) : nilai tengah sisaan sama dengan 0

\(H_1\) : nilai tengah sisaan tidak sama dengan 0

Berdasarkan uji-ttersebut, didapat p-value sebesar \(0.1592\) yang lebih besar dari taraf nyata \(5\%\) sehingga tak tolak \(H_0\) dan menandakan bahwa nilai tengah sisaan sama dengan nol.

2.6 Peramalan

2.6.1 Ramal

Peramalan dilakukan menggunakan fungsi forecast() . Contoh peramalan berikut ini dilakukan untuk h hari ke depan.

#---FORECAST---#
ramalan_aapl.da <- forecast::forecast(model_aapl.da, h = h) 
ramalan_aapl.da
##     Point Forecast     Lo 80    Hi 80     Lo 95    Hi 95
## 316     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 317     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 318     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 319     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 320     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 321     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 322     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 323     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 324     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 325     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 326     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 327     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 328     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 329     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 330     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 331     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 332     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 333     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 334     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 335     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 336     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 337     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 338     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 339     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 340     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 341     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 342     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 343     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 344     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 345     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 346     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 347     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 348     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 349     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 350     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 351     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 352     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 353     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 354     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 355     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 356     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 357     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 358     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 359     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 360     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 361     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 362     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 363     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 364     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 365     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 366     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 367     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 368     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 369     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 370     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 371     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 372     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 373     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 374     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 375     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 376     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 377     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 378     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 379     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 380     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 381     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 382     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 383     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 384     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 385     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 386     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 387     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 388     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 389     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 390     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 391     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 392     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 393     -0.0478739 -4.154434 4.058686 -6.328315 6.232567
## 394     -0.0478739 -4.154434 4.058686 -6.328315 6.232567

2.6.2 Plot

data.ramalan_aapl.da <- ramalan_aapl.da$mean
plot(ramalan_aapl.da, col = "lightskyblue4", xlab="Periode (Hari)", lwd = 2)

Berdasarkan hasil plot ramalan di atas, dapat dilihat bahwa ramalan ARIMA(0,1,1) cenderung stabil hingga akhir periode. Selanjutnya, dapat dicari nilai akurasi antara hasil ramalan dengan data uji sebagai berikut.

pt_1 <- train_aapl.ts[length(train_aapl.ts)] #nilai akhir data latih
hasil.forc.Diff <- data.ramalan_aapl.da
ramal_aapl <- diffinv(hasil.forc.Diff, differences = 1) + pt_1
#has.1 sama hasilnta dengan: cumsum(c(pt_1,hasil.forc.Diff))
ts.plot(train_aapl.ts, ramal_aapl, xlab="Periode (Hari)", 
        col = "lightskyblue4", lwd = 3,
        ylab="Saham Harga (USD)",
        main="Plot Ramalan Saham Apple Selama 79 Hari Kedepan")

Dapat dilihat bahwa rata-rata harga saham Apple diramalkan akan terus menurun setiap periodenya.

2.6.3 Perbandingan

perbandingan_aapl.da <- matrix(data=c(head(test_aapl.ts, n=h), ramal_aapl[-1]),
                     nrow = h, ncol = 2)
colnames(perbandingan_aapl.da) <- c("Aktual","Hasil Forecast")
datatable(perbandingan_aapl.da, filter = 'top', 
          options = list(pageLength = 5))
akurasi.aapl <- accuracy(ts(ramal_aapl[-1]), head(test_aapl.ts, n=h)) %>%
  as.data.frame() %>%
  cbind(Model = ramalan_aapl.da[["method"]]) %>% 
  relocate(Model, .before = 1)
row.names(akurasi.aapl) <- "AAPL"

datatable(akurasi.aapl)

Didapatkan nilai MAPE sebesar \(3.299559\%\) (kurang dari \(10\%\)) yang menandakan bahwa hasil peramalan dari model ARIMA(0,1,1) sudah sangat baik.

3 Amazon

3.1 Uji Stasioner Data

3.1.1 Plot ACF

acf(train_amzn.ts)

Berdasarkan plot ACF, terlihat bahwa plot ACF data train menurun secara perlahan (tails of slowly). Hal ini juga menjadi indikasi bahwa data tidak stasioner dalam rataan dan tidak membentuk gelombang sinus.

3.1.2 Uji ADF

tseries::adf.test(train_amzn.ts)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  train_amzn.ts
## Dickey-Fuller = -2.6387, Lag order = 6, p-value = 0.3071
## alternative hypothesis: stationary

\(H_0\) : Data tidak stasioner dalam rataan

\(H_1\) : Data stasioner dalam rataan

Berdasarkan uji ADF tersebut, didapat p-value sebesar \(0.3071\) yang lebih besar dari taraf nyata \(5\%\) sehingga tak tolak \(H_0\) dan menandakan bahwa data tidak stasioner dalam rataan. Hal ini sesuai dengan hasil eksplorasi menggunakan plot time series dan plot ACF, sehingga ketidakstasioneran model kedepannya harus ditangani.

3.1.3 Plot Box-Cox

index <- seq(1:nrow(amzn))
bc = boxcox(amzn.ts~index, lambda = seq(-2, 4, by=0.01))

#Nilai Rounded Lambda
lambda_amzn <- bc$x[which.max(bc$y)]
#SK
sk_amzn <- bc$x[bc$y > max(bc$y) - 1/2 * qchisq(.95,1)]
cat(" Lambda :", lambda_amzn,
    "\n\n Selang Kepercyaan 95% \n",
    "Batas Bawah :", min(sk_amzn), "\n Batas Bawah :", max(sk_amzn) )
##  Lambda : 0.21 
## 
##  Selang Kepercyaan 95% 
##  Batas Bawah : -0.33 
##  Batas Bawah : 0.74

Gambar di atas menunjukkan nilai rounded value (\(\lambda\)) optimum sebesar \(0.21\) dan pada selang kepercayaan \(95\%\) nilai memiliki batas bawah \(-0.33\) dan batas atas \(0.74\). Selang tersebut tidak memuat nilai satu sehingga dapat dikatakan bahwa data saham Amazon tidak stasioner dalam ragam.

3.1.4 Penanganan Ketidakstasioneran Data

train_amzn.diff <- diff(train_amzn.ts, differences = 1) 
plot.ts(train_amzn.diff, lty=1, xlab="Periode (Hari)", 
        col = "orange2", lwd = 3.5,
        main="Plot Difference Saham Amazon")

Berdasarkan plot data deret waktu, terlihat bahwa data sudah stasioner dalam rataan ditandai dengan data bergerak pada nilai tengah tertentu (tidak terdapat trend ataupun musiman pada data).

3.2 Uji Ulang

3.2.1 Plot ACF

acf(train_amzn.diff)

Berdasarkan plot tersebut, terlihat bahwa plot ACF cuts off pada lag ke 13. Sejalan dengan penanganannya, data sudah stasioner dalam rataan dan ketidakstasioneran data telah berhasil tertangani.

3.2.2 Uji ADF

tseries::adf.test(train_amzn.diff)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  train_amzn.diff
## Dickey-Fuller = -6.515, Lag order = 6, p-value = 0.01
## alternative hypothesis: stationary

\(H_0\) : Data tidak stasioner dalam rataan

\(H_1\) : Data stasioner dalam rataan

Berdasarkan uji ADF tersebut, didapat p-value sebesar \(0.01\) yang lebih kecil dari taraf nyata \(5\%\) sehingga tolak \(H_0\) atau data stasioner dalam rataan. Hal ini sesuai dengan hasil eksplorasi menggunakan plot time series dan plot ACF, sehingga dalam hal ini ketidakstasioneran data sudah berhasil ditangani dan dapat dilanjutkan ke pemodelan.

3.3 Identifikasi Model

3.3.1 Plot ACF

acf(train_amzn.diff)

Berdasarkan plot tersebut, terlihat bahwa plot ACF cenderung cuts off pada lag ke 13. Sehingga model tidak dapat di identifikasi dengan plot ACF.

3.3.2 Plot PACF

pacf(train_amzn.diff)

Berdasarkan plot tersebut, terlihat bahwa plot PACF cenderung cuts off pada lag ke 13 dan 15. Sehingga model tidak dapat di identifikasi dengan plot PACF.

3.3.3 Plot EACF

eacf(train_amzn.diff)
## AR/MA
##   0 1 2 3 4 5 6 7 8 9 10 11 12 13
## 0 o o o o o o o o o o o  o  x  o 
## 1 x o o o o o o o o o o  o  x  o 
## 2 o x o o o o o o o o o  o  o  o 
## 3 x x x o o o o o o o o  o  o  o 
## 4 x x x x o o o o o o o  o  o  o 
## 5 x x o x o o o o o o o  o  o  o 
## 6 x o o x o x o o o o o  o  o  o 
## 7 x o x x o x o o o o o  o  o  o

Identifikasi model menggunakan plot EACF dilakukan dengan melihat titik sudut kiri segitiga pada pola segitiga nol atas (pola mariks segitiga bawah). Dalam hal ini model tentatif yang terbentuk adalah ARIMA(0,1,1), ARIMA(1,1,1), ARIMA(2,1,2), ARIMA(3,1,3), dst.. Namun karena kemungkinannya sangat banyak, maka akan digunakan function agar menyingkat proses.

3.4 Pendugaan Parameter Model Tentatif

model.tentaif_amzn <- 
  model_tentatif(train_amzn.diff, p_max = 6, d = 1, q_max = 12)
## AR/MA
##   0 1 2 3 4 5 6 7 8 9 10 11 12 13
## 0 o o o o o o o o o o o  o  x  o 
## 1 x o o o o o o o o o o  o  x  o 
## 2 o x o o o o o o o o o  o  o  o 
## 3 x x x o o o o o o o o  o  o  o 
## 4 x x x x o o o o o o o  o  o  o 
## 5 x x o x o o o o o o o  o  o  o 
## 6 x o o x o x o o o o o  o  o  o 
## 7 x o x x o x o o o o o  o  o  o 
## 
## Model ARIMA dengan AIC terkecil:
## Series: data 
## ARIMA(4,1,5) 
## 
## Coefficients:
##           ar1     ar2      ar3      ar4      ma1      ma2     ma3     ma4
##       -0.2750  0.4927  -0.2505  -0.8488  -0.6975  -0.7685  0.7276  0.7147
## s.e.   0.0519  0.0554   0.0493   0.0482   0.0348   0.0276  0.0424  0.0297
##           ma5
##       -0.9762
## s.e.   0.0317
## 
## sigma^2 = 13.22:  log likelihood = -849.02
## AIC=1718.04   AICc=1718.77   BIC=1755.5
datatable(model.tentaif_amzn, filter = 'top', 
          options = list(pageLength = 5))

Berdasarkan pendugaan parameter di atas, nilai AIC terkecil \(1718.04\) dimiliki oleh model ARIMA(4,1,5) dan seluruh parameternya signifikan sehingga model yang dipilih adalah model ARIMA(4,1,5).

model_amzn.da <- Arima(train_amzn.diff, order=c(4,1,5), method="ML")

3.5 Analisis Sisaan

Model terbaik hasil identifikasi kemudian dicek asumsi sisaannya. Sisaan model ARIMA harus memenuhi asumsi normalitas, kebebasan sisaan, dan kehomogenan ragam. Diagnostik model dilakukan secara eksplorasi dan uji formal.

3.5.1 Eksplorasi Sisaan

#Eksplorasi 
sisaan_amzn.da <- model_amzn.da$residuals 
par(mfrow=c(2,2)) 
# QQ-Plot
qqnorm(sisaan_amzn.da) 
qqline(sisaan_amzn.da, col = "dodgerblue3", lwd = 2.5) 
# Plot sisaan
plot(c(1:length(sisaan_amzn.da)), sisaan_amzn.da, 
     main = "Plot Sisaan Model ARIMA",
     xlab = "Periode",
     ylab = "Nilai Sisaan")
abline(h = 0, col = "firebrick2", lty = 2, lwd=2.5)
#Plot ACF dan PACF
acf(sisaan_amzn.da) 
pacf(sisaan_amzn.da) 

Berdasarkan plot kuantil-kuantil normal, secara eksplorasi ditunjukkan sisaan menyebar normal ditandai dengan titik titik yang cenderung mengikuti garis \(45^{\circ}\). Kemudian dapat dilihat juga lebar pita sisaan yang cenderung sama menandakan bahwa sisaan memiliki ragam yang homogen. Plot ACF dan PACF sisaan ARIMA(4,1,5) juga signifikan pada 20 lag awal yang menandakan tidak saling bebas. Kondisi ini akan diuji lebih lanjut dengan uji formal.

3.5.2 Uji Formal

3.5.2.1 Sisaan Menyebar Normal

ks.test(sisaan_amzn.da,"pnorm")  #tak tolak H0 > sisaan menyebar normal
## 
##  Asymptotic one-sample Kolmogorov-Smirnov test
## 
## data:  sisaan_amzn.da
## D = 0.27186, p-value < 2.2e-16
## alternative hypothesis: two-sided

Selain dengan eksplorasi, asumsi tersebut dapat diuji menggunakan uji formal. Pada tahapan ini uji formal yang digunakan untuk normalitas adalah uji Kolmogorov-Smirnov (KS). Hipotesis pada uji KS adalah sebagai berikut.

\(H_0\) : Sisaan menyebar normal

\(H_1\) : Sisaan tidak menyebar normal

Berdasarkan uji KS tersebut, didapat p-value sebesar \(2.2e-16\) yang kurang dari taraf nyata \(5\%\) sehingga tolak \(H_0\) dan menandakan bahwa sisaan tidak menyebar normal.

3.5.2.2 Sisaan saling bebas/tidak ada autokorelasi

Box.test(sisaan_amzn.da, type = "Ljung")  #tak tolak H0 > sisaan saling bebas
## 
##  Box-Ljung test
## 
## data:  sisaan_amzn.da
## X-squared = 0.11582, df = 1, p-value = 0.7336

Selanjutnya akan dilakukan uji formal untuk kebebasan sisaan menggunakan uji Ljung-Box. Hipotesis yang digunakan adalah sebagai berikut.

\(H_0\) : Sisaan saling bebas

\(H_1\) : Sisaan tidak tidak saling bebas

Berdasarkan uji Ljung-Box tersebut, didapat p-value sebesar \(0.7336\) yang lebih besar dari taraf nyata \(5\%\) sehingga tak tolak \(H_0\) dan menandakan bahwa sisaan saling bebas.

3.5.2.3 Sisaan homogen

Box.test((sisaan_amzn.da)^2, type = "Ljung")  #tak tolak H0 > sisaan homogen
## 
##  Box-Ljung test
## 
## data:  (sisaan_amzn.da)^2
## X-squared = 5.9174, df = 1, p-value = 0.01499

Hipotesis yang digunakan untuk uji kehomogenan ragam adalah sebagai berikut.

\(H_0\) : Ragam sisaan homogen

\(H_1\) : Ragam sisaan tidak homogen

Berdasarkan uji Ljung-Box terhadap sisaan kuadrat tersebut, didapat p-value sebesar \(0.01499\) yang lebih kecil dari taraf nyata \(5\%\) sehingga tolak \(H_0\) dan menandakan bahwa ragam sisaan tidak homogen.

3.5.2.4 Nilai tengah sama dengan nol

#4) Nilai tengah sisaan sama dengan nol 
t.test(sisaan_amzn.da, mu = 0, conf.level = 0.95)  #tak tolak h0 > nilai tengah sisaan sama dengan 0
## 
##  One Sample t-test
## 
## data:  sisaan_amzn.da
## t = 1.0289, df = 313, p-value = 0.3043
## alternative hypothesis: true mean is not equal to 0
## 95 percent confidence interval:
##  -0.1895198  0.6049718
## sample estimates:
## mean of x 
##  0.207726

Terakhir, dengan uji-t, akan dicek apakah nilai tengah sisaan sama dengan nol. Hipotesis yang diujikan sebagai berikut.

\(H_0\) : nilai tengah sisaan sama dengan 0

\(H_1\) : nilai tengah sisaan tidak sama dengan 0

Berdasarkan uji-ttersebut, didapat p-value sebesar \(0.3043\) yang lebih besar dari taraf nyata \(5\%\) sehingga tak tolak \(H_0\) dan menandakan bahwa nilai tengah sisaan sama dengan nol.

3.6 Peramalan

3.6.1 Ramal

Peramalan dilakukan menggunakan fungsi forecast() . Contoh peramalan berikut ini dilakukan untuk h hari ke depan.

#---FORECAST---#
ramalan_amzn.da <- forecast::forecast(model_amzn.da, h = h) 
ramalan_amzn.da
##     Point Forecast     Lo 80    Hi 80     Lo 95    Hi 95
## 316    0.251247616 -4.429551 4.932046 -6.907416 7.409911
## 317   -0.635499219 -5.317692 4.046694 -7.796295 6.525297
## 318   -0.128136086 -4.811768 4.555496 -7.291132 7.034860
## 319   -0.637500928 -5.322216 4.047214 -7.802154 6.527152
## 320   -0.342710902 -5.063782 4.378360 -7.562966 6.877544
## 321   -0.049140884 -4.774811 4.676529 -7.276430 7.178148
## 322   -0.287710304 -5.019938 4.444518 -7.525028 6.949608
## 323    0.281044764 -4.466269 5.028359 -6.979345 7.541435
## 324   -0.316677265 -5.067468 4.434114 -7.582385 6.949031
## 325   -0.061508105 -4.812310 4.689294 -7.327233 7.204217
## 326   -0.366134987 -5.120338 4.388068 -7.637061 6.904791
## 327   -0.489678815 -5.265427 4.286069 -7.793555 6.814198
## 328   -0.162341996 -4.938168 4.613484 -7.466337 7.141653
## 329   -0.453515624 -5.238579 4.331548 -7.771639 6.864608
## 330    0.077352536 -4.707775 4.862480 -7.240868 7.395573
## 331   -0.189234844 -4.978144 4.599674 -7.513239 7.134770
## 332   -0.059287005 -4.848233 4.729659 -7.383348 7.264774
## 333   -0.112195459 -4.911606 4.687215 -7.452261 7.227870
## 334   -0.417452850 -5.220890 4.385984 -7.763675 6.928770
## 335   -0.165832430 -4.969314 4.637649 -7.512124 7.180459
## 336   -0.482471552 -5.289866 4.324922 -7.834746 6.869803
## 337   -0.150044849 -4.961043 4.660953 -7.507831 7.207742
## 338   -0.201391612 -5.013104 4.610321 -7.560271 7.157488
## 339   -0.157756598 -4.970828 4.655314 -7.518713 7.203200
## 340   -0.009559831 -4.829433 4.810314 -7.380920 7.361800
## 341   -0.298128259 -5.117989 4.521732 -7.669469 7.073212
## 342   -0.113099695 -4.933293 4.707094 -7.484949 7.258750
## 343   -0.380316300 -5.200505 4.439873 -7.752159 6.991527
## 344   -0.269171794 -5.093856 4.555512 -7.647889 7.109546
## 345   -0.232795206 -5.057484 4.591894 -7.611520 7.145930
## 346   -0.278159695 -5.106216 4.549897 -7.662035 7.105716
## 347   -0.048785922 -4.877877 4.780305 -7.434243 7.336671
## 348   -0.237673732 -5.066763 4.591416 -7.623129 7.147782
## 349   -0.092233925 -4.921490 4.737022 -7.477943 7.293476
## 350   -0.244244807 -5.074458 4.585968 -7.631418 7.142929
## 351   -0.278164151 -5.110081 4.553753 -7.667944 7.111616
## 352   -0.219827055 -5.051774 4.612120 -7.609653 7.169999
## 353   -0.337954461 -5.172515 4.496606 -7.731777 7.055868
## 354   -0.139199035 -4.973824 4.695426 -7.533120 7.254722
## 355   -0.237881636 -5.072455 4.596692 -7.631723 7.155960
## 356   -0.132748260 -4.967361 4.701864 -7.526650 7.261154
## 357   -0.159800685 -4.995847 4.676246 -7.555895 7.236294
## 358   -0.244552162 -5.080853 4.591749 -7.641036 7.151931
## 359   -0.177143600 -5.013653 4.659366 -7.573947 7.219659
## 360   -0.319898868 -5.157021 4.517223 -7.717639 7.077841
## 361   -0.203234163 -5.040907 4.634439 -7.601817 7.195348
## 362   -0.250597764 -5.088260 4.587065 -7.649164 7.147968
## 363   -0.201551981 -5.039892 4.636788 -7.601155 7.198051
## 364   -0.146427083 -4.985241 4.692387 -7.546754 7.253900
## 365   -0.224587443 -5.063421 4.614246 -7.624945 7.175770
## 366   -0.148016428 -4.987041 4.691008 -7.548665 7.252632
## 367   -0.263022213 -5.102007 4.575962 -7.663610 7.137566
## 368   -0.220880184 -5.060234 4.618474 -7.622033 7.180273
## 369   -0.241966723 -5.081293 4.597360 -7.643078 7.159145
## 370   -0.251590866 -5.091857 4.588675 -7.654139 7.150958
## 371   -0.172270256 -5.012524 4.667984 -7.574800 7.230259
## 372   -0.229315798 -5.069611 4.610979 -7.631908 7.173276
## 373   -0.154239014 -4.994527 4.686049 -7.556821 7.248343
## 374   -0.214692502 -5.055051 4.625666 -7.617381 7.187996
## 375   -0.214117257 -5.054583 4.626348 -7.616970 7.188736
## 376   -0.214444336 -5.054907 4.626019 -7.617294 7.188405
## 377   -0.262653554 -5.103595 4.578288 -7.666235 7.140928
## 378   -0.198385822 -5.039358 4.642586 -7.602013 7.205242
## 379   -0.240218404 -5.081267 4.600830 -7.643963 7.163526
## 380   -0.184696784 -5.025805 4.656411 -7.588533 7.219139
## 381   -0.195754671 -5.036900 4.645391 -7.599648 7.208138
## 382   -0.209432487 -5.050613 4.631748 -7.613379 7.194514
## 383   -0.189518701 -5.030733 4.651695 -7.593516 7.214479
## 384   -0.246091774 -5.087380 4.595196 -7.650202 7.158019
## 385   -0.207909291 -5.049245 4.633427 -7.612094 7.196275
## 386   -0.239660394 -5.081026 4.601705 -7.643890 7.164569
## 387   -0.214848236 -5.056438 4.626741 -7.619421 7.189724
## 388   -0.198859478 -5.040423 4.642704 -7.603391 7.205672
## 389   -0.215489059 -5.057103 4.626125 -7.620098 7.189120
## 390   -0.182303106 -5.023907 4.659301 -7.586898 7.222292
## 391   -0.224689229 -5.066267 4.616888 -7.629243 7.179864
## 392   -0.206088166 -5.047681 4.635505 -7.610666 7.198490
## 393   -0.226283716 -5.067854 4.615287 -7.630827 7.178260
## 394   -0.229116218 -5.070884 4.612652 -7.633961 7.175729

3.6.2 Plot

data.ramalan_amzn.da <- ramalan_amzn.da$mean
plot(ramalan_amzn.da, col = "orange2", xlab="Periode (Hari)", lwd = 2.5)

Berdasarkan hasil plot ramalan di atas, dapat dilihat bahwa ramalan ARIMA(4,1,5) cenderung stabil hingga akhir periode. Selanjutnya, dapat dicari nilai akurasi antara hasil ramalan dengan data uji sebagai berikut.

pt_1 <- train_amzn.ts[length(train_amzn.ts)] #nilai akhir data latih
hasil.forc.Diff <- data.ramalan_amzn.da
ramal_amzn <- diffinv(hasil.forc.Diff, differences = 1) + pt_1
#has.1 sama hasilnta dengan: cumsum(c(pt_1,hasil.forc.Diff))
ts.plot(train_amzn.ts, ramal_amzn, xlab="Periode (Hari)", 
        col = "orange2", lwd = 3,
        ylab="Saham Harga (USD)",
        main="Plot Ramalan Saham Amazon Selama 79 Hari Kedepan")

Dapat dilihat bahwa rata-rata harga saham amazon diramalkan akan terus menurun setiap periodenya.

3.6.3 Perbandingan

perbandingan_amzn.da <- matrix(data=c(head(test_amzn.ts, n=h), ramal_amzn[-1]),
                     nrow = h, ncol = 2)
colnames(perbandingan_amzn.da) <- c("Aktual","Hasil Forecast")
datatable(perbandingan_amzn.da, filter = 'top', 
          options = list(pageLength = 5))
akurasi.amzn <- accuracy(ts(ramal_amzn[-1]), head(test_amzn.ts, n=h)) %>%
  as.data.frame() %>%
  cbind(Model = ramalan_amzn.da[["method"]]) %>% 
  relocate(Model, .before = 1)
row.names(akurasi.amzn) <- "AMZN"
datatable(akurasi.amzn)

Didapatkan nilai MAPE sebesar \(12.49469\%\) (lebih dari \(10\%\)) yang menandakan bahwa hasil peramalan dari model ARIMA(4,1,5) sudah baik.

4 Google

4.1 Uji Stasioner Data

4.1.1 Plot ACF

acf(train_goog.ts)

Berdasarkan plot ACF, terlihat bahwa plot ACF data train menurun secara perlahan (tails of slowly). Hal ini juga menjadi indikasi bahwa data tidak stasioner dalam rataan dan tidak membentuk gelombang sinus.

4.1.2 Uji ADF

tseries::adf.test(train_goog.ts)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  train_goog.ts
## Dickey-Fuller = -2.2318, Lag order = 6, p-value = 0.4787
## alternative hypothesis: stationary

\(H_0\) : Data tidak stasioner dalam rataan

\(H_1\) : Data stasioner dalam rataan

Berdasarkan uji ADF tersebut, didapat p-value sebesar \(0.4787\) yang lebih besar dari taraf nyata \(5\%\) sehingga tak tolak \(H_0\) dan menandakan bahwa data tidak stasioner dalam rataan. Hal ini sesuai dengan hasil eksplorasi menggunakan plot time series dan plot ACF, sehingga ketidakstasioneran model kedepannya harus ditangani.

4.1.3 Plot Box-Cox

index <- seq(1:nrow(goog))
bc = boxcox(goog.ts~index, lambda = seq(-2, 4, by=0.01))

#Nilai Rounded Lambda
lambda_goog <- bc$x[which.max(bc$y)]
#SK
sk_goog <- bc$x[bc$y > max(bc$y) - 1/2 * qchisq(.95,1)]
cat(" Lambda :", lambda_goog,
    "\n\n Selang Kepercyaan 95% \n",
    "Batas Bawah :", min(sk_goog), "\n Batas Atas  :", max(sk_goog) )
##  Lambda : 0.51 
## 
##  Selang Kepercyaan 95% 
##  Batas Bawah : -0.23 
##  Batas Atas  : 1.25

Gambar di atas menunjukkan nilai rounded value (\(\lambda\)) optimum sebesar \(0.51\) dan pada selang kepercayaan \(95\%\) nilai memiliki batas bawah \(-0.23\) dan batas atas \(1.25\). Selang tersebut memuat nilai satu sehingga dapat dikatakan bahwa data saham Google stasioner dalam ragam.

4.1.4 Penanganan Ketidakstasioneran Data

train_goog.diff <- diff(train_goog.ts, differences = 1) 
plot.ts(train_goog.diff, lty=1, xlab="Periode (Hari)", 
        col = "gold3", lwd = 3.5,
        main="Plot Difference Saham Google")

Berdasarkan plot data deret waktu, terlihat bahwa data sudah stasioner dalam rataan ditandai dengan data bergerak pada nilai tengah tertentu (tidak terdapat trend ataupun musiman pada data).

4.2 Uji Ulang

4.2.1 Plot ACF

acf(train_goog.diff)

Berdasarkan plot ACF tersebut, terlihat bahwa tidak ada satupun lag yang cut off. Sejalan dengan penanganannya, data sudah stasioner dalam rataan dan ketidakstasioneran data telah berhasil tertangani.

4.2.2 Uji ADF

tseries::adf.test(train_goog.diff)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  train_goog.diff
## Dickey-Fuller = -7.859, Lag order = 6, p-value = 0.01
## alternative hypothesis: stationary

\(H_0\) : Data tidak stasioner dalam rataan

\(H_1\) : Data stasioner dalam rataan

Berdasarkan uji ADF tersebut, didapat p-value sebesar \(0.01\) yang lebih kecil dari taraf nyata \(5\%\) sehingga tolak \(H_0\) atau data stasioner dalam rataan. Hal ini sesuai dengan hasil eksplorasi menggunakan plot time series dan plot ACF, sehingga dalam hal ini ketidakstasioneran data sudah berhasil ditangani dan dapat dilanjutkan ke pemodelan.

4.3 Identifikasi Model

4.3.1 Plot ACF

acf(train_goog.diff)

Berdasarkan plot ACF tersebut, terlihat bahwa tidak ada satupun lag yang cut off. Maka model tidak dapat di identifikasi dengan plot ACF.

4.3.2 Plot PACF

pacf(train_goog.diff)

Sama dengan plot ACF nya, pada plot PACF terlihat tidak ada satupun lag yang cut off. Maka model tidak dapat di identifikasi dengan plot PACF.

4.3.3 Plot EACF

eacf(train_goog.diff)
## AR/MA
##   0 1 2 3 4 5 6 7 8 9 10 11 12 13
## 0 o o o o o o o o o o o  o  o  o 
## 1 x o o o o o o o o o o  o  o  o 
## 2 x o o o o o o o o o o  o  o  o 
## 3 x o o o o o o o o o o  o  o  o 
## 4 o x o x o o o o o o o  o  o  o 
## 5 o x x x x o o o o o o  o  o  o 
## 6 x x x x x x o o o o o  o  o  o 
## 7 x x x o o o o o o o o  o  o  o

Identifikasi model menggunakan plot EACF dilakukan dengan melihat titik sudut kiri segitiga pada pola segitiga nol atas (pola mariks segitiga bawah). Dalam hal ini model tentatif yang terbentuk adalah ARIMA(0,1,1), ARIMA(1,1,1), ARIMA(2,1,2), ARIMA(3,1,3), dst.. Namun karena kemungkinannya sangat banyak, maka akan digunakan function agar menyingkat proses.

4.4 Pendugaan Parameter Model Tentatif

model.tentaif_goog <- 
  model_tentatif(train_goog.diff, p_max = 6, d = 1, q_max = 12)
## AR/MA
##   0 1 2 3 4 5 6 7 8 9 10 11 12 13
## 0 o o o o o o o o o o o  o  o  o 
## 1 x o o o o o o o o o o  o  o  o 
## 2 x o o o o o o o o o o  o  o  o 
## 3 x o o o o o o o o o o  o  o  o 
## 4 o x o x o o o o o o o  o  o  o 
## 5 o x x x x o o o o o o  o  o  o 
## 6 x x x x x x o o o o o  o  o  o 
## 7 x x x o o o o o o o o  o  o  o 
## 
## Model ARIMA dengan AIC terkecil:
## Series: data 
## ARIMA(0,1,1) 
## 
## Coefficients:
##          ma1
##       -1.000
## s.e.   0.013
## 
## sigma^2 = 7.453:  log likelihood = -760.86
## AIC=1525.72   AICc=1525.76   BIC=1533.21
datatable(model.tentaif_goog, filter = 'top', 
          options = list(pageLength = 5))

Berdasarkan pendugaan parameter di atas, nilai AIC terkecil \(1525.72\) dimiliki oleh model ARIMA(0,1,1) dan seluruh parameternya signifikan sehingga model yang dipilih adalah model ARIMA(0,1,1).

model_goog.da <- Arima(train_goog.diff, order=c(0,1,1), method="ML")

4.5 Analisis Sisaan

Model terbaik hasil identifikasi kemudian dicek asumsi sisaannya. Sisaan model ARIMA harus memenuhi asumsi normalitas, kebebasan sisaan, dan kehomogenan ragam. Diagnostik model dilakukan secara eksplorasi dan uji formal.

4.5.1 Eksplorasi Sisaan

#Eksplorasi 
sisaan_goog.da <- model_goog.da$residuals 
par(mfrow=c(2,2)) 
# QQ-Plot
qqnorm(sisaan_goog.da) 
qqline(sisaan_goog.da, col = "dodgerblue3", lwd = 2.5) 
# Plot sisaan
plot(c(1:length(sisaan_goog.da)), sisaan_goog.da, 
     main = "Plot Sisaan Model ARIMA",
     xlab = "Periode",
     ylab = "Nilai Sisaan")
abline(h = 0, col = "firebrick2", lty = 2, lwd=2.5)
#Plot ACF dan PACF
acf(sisaan_goog.da) 
pacf(sisaan_goog.da) 

Berdasarkan plot kuantil-kuantil normal, secara eksplorasi ditunjukkan sisaan menyebar normal ditandai dengan titik titik yang cenderung mengikuti garis \(45^{\circ}\). Kemudian dapat dilihat juga lebar pita sisaan yang cenderung sama menandakan bahwa sisaan memiliki ragam yang homogen. Plot ACF dan PACF sisaan ARIMA(0,1,1) juga tidak signifikan pada 20 lag awal yang menandakan saling bebas. Kondisi ini akan diuji lebih lanjut dengan uji formal.

4.5.2 Uji Formal

4.5.2.1 Sisaan Menyebar Normal

ks.test(sisaan_goog.da,"pnorm")  #tak tolak H0 > sisaan menyebar normal
## 
##  Asymptotic one-sample Kolmogorov-Smirnov test
## 
## data:  sisaan_goog.da
## D = 0.23999, p-value = 4.441e-16
## alternative hypothesis: two-sided

Selain dengan eksplorasi, asumsi tersebut dapat diuji menggunakan uji formal. Pada tahapan ini uji formal yang digunakan untuk normalitas adalah uji Kolmogorov-Smirnov (KS). Hipotesis pada uji KS adalah sebagai berikut.

\(H_0\) : Sisaan menyebar normal

\(H_1\) : Sisaan tidak menyebar normal

Berdasarkan uji KS tersebut, didapat p-value sebesar \(4.441\times10^{-16}\) yang kurang dari taraf nyata \(5\%\) sehingga tolak \(H_0\) dan menandakan bahwa sisaan tidak menyebar normal. Hal ini sesuai dengan hasil eksplorasi menggunakan plot kuantil-kuantil normal.

4.5.2.2 Sisaan saling bebas/tidak ada autokorelasi

Box.test(sisaan_goog.da, type = "Ljung")  #tak tolak H0 > sisaan saling bebas
## 
##  Box-Ljung test
## 
## data:  sisaan_goog.da
## X-squared = 0.20035, df = 1, p-value = 0.6544

Selanjutnya akan dilakukan uji formal untuk kebebasan sisaan menggunakan uji Ljung-Box. Hipotesis yang digunakan adalah sebagai berikut.

\(H_0\) : Sisaan saling bebas

\(H_1\) : Sisaan tidak tidak saling bebas

Berdasarkan uji Ljung-Box tersebut, didapat p-value sebesar \(0.6h4\) yang lebih besar dari taraf nyata \(5\%\) sehingga tak tolak \(H_0\) dan menandakan bahwa sisaan saling bebas. Hal ini sesuai dengan hasil eksplorasi menggunakan plot ACF dan PACF.

4.5.2.3 Sisaan homogen

Box.test((sisaan_goog.da)^2, type = "Ljung")  #tak tolak H0 > sisaan homogen
## 
##  Box-Ljung test
## 
## data:  (sisaan_goog.da)^2
## X-squared = 0.20183, df = 1, p-value = 0.6532

Hipotesis yang digunakan untuk uji kehomogenan ragam adalah sebagai berikut.

\(H_0\) : Ragam sisaan homogen

\(H_1\) : Ragam sisaan tidak homogen

Berdasarkan uji Ljung-Box terhadap sisaan kuadrat tersebut, didapat p-value sebesar \(0.6532\) yang lebih besar dari taraf nyata \(5\%\) sehingga tak tolak \(H_0\) dan menandakan bahwa ragam sisaan homogen.

4.5.2.4 Nilai tengah sama dengan nol

#4) Nilai tengah sisaan sama dengan nol 
t.test(sisaan_goog.da, mu = 0, conf.level = 0.95)  #tak tolak h0 > nilai tengah sisaan sama dengan 0
## 
##  One Sample t-test
## 
## data:  sisaan_goog.da
## t = 1.0217, df = 313, p-value = 0.3077
## alternative hypothesis: true mean is not equal to 0
## 95 percent confidence interval:
##  -0.1452610  0.4590431
## sample estimates:
## mean of x 
## 0.1568911

Terakhir, dengan uji-t, akan dicek apakah nilai tengah sisaan sama dengan nol. Hipotesis yang diujikan sebagai berikut.

\(H_0\) : nilai tengah sisaan sama dengan 0

\(H_1\) : nilai tengah sisaan tidak sama dengan 0

Berdasarkan uji-ttersebut, didapat p-value sebesar \(0.3077\) yang lebih besar dari taraf nyata \(5\%\) sehingga tak tolak \(H_0\) dan menandakan bahwa nilai tengah sisaan sama dengan nol.

4.6 Peramalan

4.6.1 Ramal

Peramalan dilakukan menggunakan fungsi forecast() . Contoh peramalan berikut ini dilakukan untuk h hari ke depan.

#---FORECAST---#
ramalan_goog.da <- forecast::forecast(model_goog.da, h = h) 
ramalan_goog.da
##     Point Forecast     Lo 80    Hi 80     Lo 95    Hi 95
## 316     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 317     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 318     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 319     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 320     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 321     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 322     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 323     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 324     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 325     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 326     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 327     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 328     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 329     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 330     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 331     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 332     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 333     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 334     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 335     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 336     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 337     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 338     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 339     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 340     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 341     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 342     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 343     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 344     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 345     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 346     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 347     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 348     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 349     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 350     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 351     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 352     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 353     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 354     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 355     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 356     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 357     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 358     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 359     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 360     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 361     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 362     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 363     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 364     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 365     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 366     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 367     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 368     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 369     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 370     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 371     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 372     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 373     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 374     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 375     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 376     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 377     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 378     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 379     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 380     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 381     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 382     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 383     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 384     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 385     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 386     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 387     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 388     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 389     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 390     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 391     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 392     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 393     -0.1272436 -3.631566 3.377078 -5.486642 5.232154
## 394     -0.1272436 -3.631566 3.377078 -5.486642 5.232154

4.6.2 Plot

data.ramalan_goog.da <- ramalan_goog.da$mean
plot(ramalan_goog.da, xlab="Periode (Hari)", col = "gold3", lwd = 2.5)

Berdasarkan hasil plot ramalan di atas, dapat dilihat bahwa ramalan ARIMA(0,1,1) cenderung stabil hingga akhir periode. Selanjutnya, dapat dicari nilai akurasi antara hasil ramalan dengan data uji sebagai berikut.

pt_1 <- train_goog.ts[length(train_goog.ts)] #nilai akhir data latih
hasil.forc.Diff <- data.ramalan_goog.da
ramal_goog <- diffinv(hasil.forc.Diff, differences = 1) + pt_1
#has.1 sama hasilnta dengan: cumsum(c(pt_1,hasil.forc.Diff))
ts.plot(train_goog.ts, ramal_goog, xlab="Periode (Hari)", 
        col = "gold3", lwd = 3.5,
        ylab="Saham Harga (USD)",
        main="Plot Ramalan Saham Google Selama 79 Hari Kedepan")

Dapat dilihat bahwa rata-rata harga saham Google diramalkan akan terus menurun setiap periodenya.

4.6.3 Perbandingan

perbandingan_goog.da <- matrix(data=c(head(test_goog.ts, n=h), ramal_goog[-1]),
                     nrow = h, ncol = 2)
colnames(perbandingan_goog.da) <- c("Aktual","Hasil Forecast")
datatable(perbandingan_goog.da, filter = 'top', 
          options = list(pageLength = 5))
akurasi.goog <- accuracy(ts(ramal_goog[-1]), head(test_goog.ts, n=h)) %>%
  as.data.frame() %>%
  cbind(Model = ramalan_goog.da[["method"]]) %>% 
  relocate(Model, .before = 1)
row.names(akurasi.goog) <- "GOOG"
datatable(akurasi.goog)

Didapatkan nilai MAPE sebesar \(11.24534\%\) (lebih dari \(10\%\)) yang menandakan bahwa hasil peramalan dari model ARIMA(0,1,1) sudah baik.

5 META

5.1 Uji Stasioner Data

5.1.1 Plot ACF

acf(train_meta.ts)

Berdasarkan plot ACF, terlihat bahwa plot ACF data train menurun secara perlahan (tails of slowly). Hal ini juga menjadi indikasi bahwa data tidak stasioner dalam rataan dan tidak membentuk gelombang sinus.

5.1.2 Uji ADF

tseries::adf.test(train_meta.ts)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  train_meta.ts
## Dickey-Fuller = -1.8162, Lag order = 6, p-value = 0.6539
## alternative hypothesis: stationary

\(H_0\) : Data tidak stasioner dalam rataan

\(H_1\) : Data stasioner dalam rataan

Berdasarkan uji ADF tersebut, didapat p-value sebesar \(0.6539\) yang lebih besar dari taraf nyata \(5\%\) sehingga tak tolak \(H_0\) dan menandakan bahwa data tidak stasioner dalam rataan. Hal ini sesuai dengan hasil eksplorasi menggunakan plot time series dan plot ACF, sehingga ketidakstasioneran model kedepannya harus ditangani.

5.1.3 Plot Box-Cox

index <- seq(1:nrow(meta))
bc = boxcox(meta.ts~index, lambda = seq(-2, 4, by=0.01))

#Nilai Rounded Lambda
lambda_meta <- bc$x[which.max(bc$y)]
#SK
sk_meta <- bc$x[bc$y > max(bc$y) - 1/2 * qchisq(.95,1)]
cat(" Lambda :", lambda_meta,
    "\n\n Selang Kepercyaan 95% \n",
    "Batas Bawah :", min(sk_meta), "\n Batas Atas  :", max(sk_meta) )
##  Lambda : 0.13 
## 
##  Selang Kepercyaan 95% 
##  Batas Bawah : -0.17 
##  Batas Atas  : 0.42

Gambar di atas menunjukkan nilai rounded value (\(\lambda\)) optimum sebesar \(0.13\) dan pada selang kepercayaan \(95\%\) nilai memiliki batas bawah \(-0.17\) dan batas atas \(0.42\). Selang tersebut tidak memuat nilai satu sehingga dapat dikatakan bahwa data saham amazon tidak stasioner dalam ragam.

5.1.4 Penanganan Ketidakstasioneran Data

train_meta.diff <- diff(train_meta.ts, differences = 1) 
plot.ts(train_meta.diff, lty=1, xlab="Periode (Tahun)", 
        col = "dodgerblue3", lwd = 3.5,
        main="Plot Difference Saham META")

Berdasarkan plot data deret waktu, terlihat bahwa data sudah stasioner dalam rataan ditandai dengan data bergerak pada nilai tengah tertentu (tidak terdapat trend ataupun musiman pada data).

5.2 Uji Ulang

5.2.1 Plot ACF

acf(train_meta.diff)

Berdasarkan plot tersebut, terlihat bahwa plot ACF cuts off pada lag ke 20. Sejalan dengan penanganannya, data sudah stasioner dalam rataan dan ketidakstasioneran data telah berhasil tertangani.

5.2.2 Uji ADF

tseries::adf.test(train_meta.diff)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  train_meta.diff
## Dickey-Fuller = -7.36, Lag order = 6, p-value = 0.01
## alternative hypothesis: stationary

\(H_0\) : Data tidak stasioner dalam rataan

\(H_1\) : Data stasioner dalam rataan

Berdasarkan uji ADF tersebut, didapat p-value sebesar \(0.01\) yang lebih kecil dari taraf nyata \(5\%\) sehingga tolak \(H_0\) atau data stasioner dalam rataan. Hal ini sesuai dengan hasil eksplorasi menggunakan plot time series dan plot ACF, sehingga dalam hal ini ketidakstasioneran data sudah berhasil ditangani dan dapat dilanjutkan ke pemodelan.

5.3 Identifikasi Model

5.3.1 Plot ACF

acf(train_meta.diff)

Berdasarkan plot tersebut, terlihat bahwa plot ACF cenderung cuts off pada lag ke 20. Maka model tidak dapat di identifikasi dengan plot ACF.

5.3.2 Plot PACF

pacf(train_meta.diff)

Berdasarkan plot tersebut, terlihat bahwa plot PACF cenderung cuts off pada lag ke 20. Maka model tidak dapat di identifikasi dengan plot PACF.

5.3.3 Plot EACF

eacf(train_meta.diff)
## AR/MA
##   0 1 2 3 4 5 6 7 8 9 10 11 12 13
## 0 o o o o o o o o o o o  o  o  o 
## 1 x o o o o o o o o o o  o  o  o 
## 2 x x o o o o o o o o o  o  o  o 
## 3 x x x o o o o o o o o  o  o  o 
## 4 x x x o o o o o o o o  o  o  o 
## 5 x x o o o o o o o o o  o  o  o 
## 6 x x x o o x o o o o o  o  o  o 
## 7 x x x o o x x o o o o  o  o  o

Identifikasi model menggunakan plot EACF dilakukan dengan melihat titik sudut kiri segitiga pada pola segitiga nol atas (pola mariks segitiga bawah). Dalam hal ini model tentatif yang terbentuk adalah ARIMA(0,1,1), ARIMA(1,1,1), ARIMA(2,1,2), ARIMA(3,1,3), dst.. Namun karena kemungkinannya sangat banyak, maka akan digunakan function agar menyingkat proses.

5.4 Pendugaan Parameter Model Tentatif

model.tentaif_meta <- 
  model_tentatif(train_meta.diff, p_max = 6, d = 1, q_max = 12)
## AR/MA
##   0 1 2 3 4 5 6 7 8 9 10 11 12 13
## 0 o o o o o o o o o o o  o  o  o 
## 1 x o o o o o o o o o o  o  o  o 
## 2 x x o o o o o o o o o  o  o  o 
## 3 x x x o o o o o o o o  o  o  o 
## 4 x x x o o o o o o o o  o  o  o 
## 5 x x o o o o o o o o o  o  o  o 
## 6 x x x o o x o o o o o  o  o  o 
## 7 x x x o o x x o o o o  o  o  o 
## 
## Model ARIMA dengan AIC terkecil:
## Series: data 
## ARIMA(0,1,1) 
## 
## Coefficients:
##           ma1
##       -0.9853
## s.e.   0.0100
## 
## sigma^2 = 62.76:  log likelihood = -1093.2
## AIC=2190.39   AICc=2190.43   BIC=2197.88
datatable(model.tentaif_meta, filter = 'top', 
          options = list(pageLength = 5))

Berdasarkan pendugaan parameter di atas, nilai AIC terkecil \(2190.39\) dimiliki oleh model ARIMA(0,1,1) dan seluruh parameternya signifikan sehingga model yang dipilih adalah model ARIMA(0,1,1) .

model_meta.da <- Arima(train_meta.diff, order=c(0,1,1), method="ML")

5.5 Analisis Sisaan

Model terbaik hasil identifikasi kemudian dicek asumsi sisaannya. Sisaan model ARIMA harus memenuhi asumsi normalitas, kebebasan sisaan, dan kehomogenan ragam. Diagnostik model dilakukan secara eksplorasi dan uji formal.

5.5.1 Eksplorasi Sisaan

#Eksplorasi 
sisaan_meta.da <- model_meta.da$residuals 
par(mfrow=c(2,2)) 
# QQ-Plot
qqnorm(sisaan_meta.da) 
qqline(sisaan_meta.da, col = "dodgerblue3", lwd = 2.5) 
# Plot sisaan
plot(c(1:length(sisaan_meta.da)), sisaan_meta.da, 
     main = "Plot Sisaan Model ARIMA",
     xlab = "Periode",
     ylab = "Nilai Sisaan")
abline(h = 0, col = "firebrick2", lty = 2, lwd=2.5)
#Plot ACF dan PACF
acf(sisaan_meta.da) 
pacf(sisaan_meta.da) 

Berdasarkan plot kuantil-kuantil normal, secara eksplorasi ditunjukkan sisaan tidak menyebar normal ditandai dengan tidak semua titik (ada pencilan) mengikuti garis \(45^{\circ}\). Kemudian dapat dilihat juga lebar pita sisaan yang cenderung tidak sama dikarenakan adanya pencilan menandakan bahwa sisaan memiliki ragam yang tidak homogen. Plot ACF dan PACF sisaan ARIMA(0,1,1) juga tidak signifikan pada 20 lag awal yang menandakan saling bebas. Kondisi ini akan diuji lebih lanjut dengan uji formal.

5.5.2 Uji Formal

5.5.2.1 Sisaan Menyebar Normal

ks.test(sisaan_meta.da,"pnorm")  #tak tolak H0 > sisaan menyebar normal
## 
##  Asymptotic one-sample Kolmogorov-Smirnov test
## 
## data:  sisaan_meta.da
## D = 0.38867, p-value < 2.2e-16
## alternative hypothesis: two-sided

Selain dengan eksplorasi, asumsi tersebut dapat diuji menggunakan uji formal. Pada tahapan ini uji formal yang digunakan untuk normalitas adalah uji Kolmogorov-Smirnov (KS). Hipotesis pada uji KS adalah sebagai berikut.

\(H_0\) : Sisaan menyebar normal

\(H_1\) : Sisaan tidak menyebar normal

Berdasarkan uji KS tersebut, didapat p-value sebesar \(2.2\times 10^{-16}\) yang kurang dari taraf nyata \(5\%\) sehingga tolak \(H_0\) dan menandakan bahwa sisaan tidak menyebar normal. Hal ini sesuai dengan hasil eksplorasi menggunakan plot kuantil-kuantil normal.

5.5.2.2 Sisaan saling bebas/tidak ada autokorelasi

Box.test(sisaan_meta.da, type = "Ljung")  #tak tolak H0 > sisaan saling bebas
## 
##  Box-Ljung test
## 
## data:  sisaan_meta.da
## X-squared = 0.6458, df = 1, p-value = 0.4216

Selanjutnya akan dilakukan uji formal untuk kebebasan sisaan menggunakan uji Ljung-Box. Hipotesis yang digunakan adalah sebagai berikut.

\(H_0\) : Sisaan saling bebas

\(H_1\) : Sisaan tidak tidak saling bebas

Berdasarkan uji Ljung-Box tersebut, didapat p-value sebesar \(0.4216\) yang lebih besar dari taraf nyata \(5\%\) sehingga tak tolak \(H_0\) dan menandakan bahwa sisaan saling bebas. Hal ini sesuai dengan hasil eksplorasi menggunakan plot ACF dan PACF.

5.5.2.3 Sisaan homogen

Box.test((sisaan_meta.da)^2, type = "Ljung")  #tak tolak H0 > sisaan homogen
## 
##  Box-Ljung test
## 
## data:  (sisaan_meta.da)^2
## X-squared = 0.034479, df = 1, p-value = 0.8527

Hipotesis yang digunakan untuk uji kehomogenan ragam adalah sebagai berikut.

\(H_0\) : Ragam sisaan homogen

\(H_1\) : Ragam sisaan tidak homogen

Berdasarkan uji Ljung-Box terhadap sisaan kuadrat tersebut, didapat p-value sebesar \(0.8527\) yang lebih besar dari taraf nyata \(5\%\) sehingga tak tolak \(H_0\) dan menandakan bahwa ragam sisaan homogen.

5.5.2.4 Nilai tengah sama dengan nol

#4) Nilai tengah sisaan sama dengan nol 
t.test(sisaan_meta.da, mu = 0, conf.level = 0.95)  #tak tolak h0 > nilai tengah sisaan sama dengan 0
## 
##  One Sample t-test
## 
## data:  sisaan_meta.da
## t = 1.5232, df = 313, p-value = 0.1287
## alternative hypothesis: true mean is not equal to 0
## 95 percent confidence interval:
##  -0.1976273  1.5523680
## sample estimates:
## mean of x 
## 0.6773703

Terakhir, dengan uji-t, akan dicek apakah nilai tengah sisaan sama dengan nol. Hipotesis yang diujikan sebagai berikut.

\(H_0\) : nilai tengah sisaan sama dengan 0

\(H_1\) : nilai tengah sisaan tidak sama dengan 0

Berdasarkan uji-ttersebut, didapat p-value sebesar \(0.1287\) yang lebih besar dari taraf nyata \(5\%\) sehingga tak tolak \(H_0\) dan menandakan bahwa nilai tengah sisaan sama dengan nol.

5.6 Peramalan

5.6.1 Ramal

Peramalan dilakukan menggunakan fungsi forecast() . Contoh peramalan berikut ini dilakukan untuk h hari ke depan.

#---FORECAST---#
ramalan_meta.da <- forecast::forecast(model_meta.da, h = h) 
ramalan_meta.da
##     Point Forecast     Lo 80    Hi 80     Lo 95    Hi 95
## 316      0.7316728 -9.420903 10.88425 -14.79535 16.25870
## 317      0.7316728 -9.422003 10.88535 -14.79704 16.26038
## 318      0.7316728 -9.423104 10.88645 -14.79872 16.26206
## 319      0.7316728 -9.424204 10.88755 -14.80040 16.26375
## 320      0.7316728 -9.425304 10.88865 -14.80208 16.26543
## 321      0.7316728 -9.426404 10.88975 -14.80376 16.26711
## 322      0.7316728 -9.427503 10.89085 -14.80545 16.26879
## 323      0.7316728 -9.428603 10.89195 -14.80713 16.27047
## 324      0.7316728 -9.429703 10.89305 -14.80881 16.27216
## 325      0.7316728 -9.430802 10.89415 -14.81049 16.27384
## 326      0.7316728 -9.431901 10.89525 -14.81217 16.27552
## 327      0.7316728 -9.433000 10.89635 -14.81385 16.27720
## 328      0.7316728 -9.434099 10.89745 -14.81553 16.27888
## 329      0.7316728 -9.435198 10.89854 -14.81721 16.28056
## 330      0.7316728 -9.436297 10.89964 -14.81890 16.28224
## 331      0.7316728 -9.437396 10.90074 -14.82058 16.28392
## 332      0.7316728 -9.438494 10.90184 -14.82226 16.28560
## 333      0.7316728 -9.439593 10.90294 -14.82394 16.28728
## 334      0.7316728 -9.440691 10.90404 -14.82562 16.28896
## 335      0.7316728 -9.441789 10.90513 -14.82729 16.29064
## 336      0.7316728 -9.442887 10.90623 -14.82897 16.29232
## 337      0.7316728 -9.443985 10.90733 -14.83065 16.29400
## 338      0.7316728 -9.445083 10.90843 -14.83233 16.29568
## 339      0.7316728 -9.446181 10.90953 -14.83401 16.29736
## 340      0.7316728 -9.447278 10.91062 -14.83569 16.29904
## 341      0.7316728 -9.448376 10.91172 -14.83737 16.30071
## 342      0.7316728 -9.449473 10.91282 -14.83905 16.30239
## 343      0.7316728 -9.450570 10.91392 -14.84072 16.30407
## 344      0.7316728 -9.451668 10.91501 -14.84240 16.30575
## 345      0.7316728 -9.452765 10.91611 -14.84408 16.30743
## 346      0.7316728 -9.453862 10.91721 -14.84576 16.30910
## 347      0.7316728 -9.454958 10.91830 -14.84744 16.31078
## 348      0.7316728 -9.456055 10.91940 -14.84911 16.31246
## 349      0.7316728 -9.457152 10.92050 -14.85079 16.31414
## 350      0.7316728 -9.458248 10.92159 -14.85247 16.31581
## 351      0.7316728 -9.459344 10.92269 -14.85414 16.31749
## 352      0.7316728 -9.460440 10.92379 -14.85582 16.31916
## 353      0.7316728 -9.461536 10.92488 -14.85750 16.32084
## 354      0.7316728 -9.462632 10.92598 -14.85917 16.32252
## 355      0.7316728 -9.463728 10.92707 -14.86085 16.32419
## 356      0.7316728 -9.464824 10.92817 -14.86252 16.32587
## 357      0.7316728 -9.465920 10.92927 -14.86420 16.32754
## 358      0.7316728 -9.467015 10.93036 -14.86587 16.32922
## 359      0.7316728 -9.468110 10.93146 -14.86755 16.33090
## 360      0.7316728 -9.469206 10.93255 -14.86922 16.33257
## 361      0.7316728 -9.470301 10.93365 -14.87090 16.33425
## 362      0.7316728 -9.471396 10.93474 -14.87257 16.33592
## 363      0.7316728 -9.472491 10.93584 -14.87425 16.33759
## 364      0.7316728 -9.473585 10.93693 -14.87592 16.33927
## 365      0.7316728 -9.474680 10.93803 -14.87760 16.34094
## 366      0.7316728 -9.475775 10.93912 -14.87927 16.34262
## 367      0.7316728 -9.476869 10.94021 -14.88094 16.34429
## 368      0.7316728 -9.477963 10.94131 -14.88262 16.34596
## 369      0.7316728 -9.479058 10.94240 -14.88429 16.34764
## 370      0.7316728 -9.480152 10.94350 -14.88597 16.34931
## 371      0.7316728 -9.481246 10.94459 -14.88764 16.35098
## 372      0.7316728 -9.482339 10.94569 -14.88931 16.35266
## 373      0.7316728 -9.483433 10.94678 -14.89098 16.35433
## 374      0.7316728 -9.484527 10.94787 -14.89266 16.35600
## 375      0.7316728 -9.485620 10.94897 -14.89433 16.35767
## 376      0.7316728 -9.486714 10.95006 -14.89600 16.35935
## 377      0.7316728 -9.487807 10.95115 -14.89767 16.36102
## 378      0.7316728 -9.488900 10.95225 -14.89934 16.36269
## 379      0.7316728 -9.489993 10.95334 -14.90102 16.36436
## 380      0.7316728 -9.491086 10.95443 -14.90269 16.36603
## 381      0.7316728 -9.492179 10.95552 -14.90436 16.36770
## 382      0.7316728 -9.493271 10.95662 -14.90603 16.36938
## 383      0.7316728 -9.494364 10.95771 -14.90770 16.37105
## 384      0.7316728 -9.495456 10.95880 -14.90937 16.37272
## 385      0.7316728 -9.496549 10.95989 -14.91104 16.37439
## 386      0.7316728 -9.497641 10.96099 -14.91271 16.37606
## 387      0.7316728 -9.498733 10.96208 -14.91438 16.37773
## 388      0.7316728 -9.499825 10.96317 -14.91605 16.37940
## 389      0.7316728 -9.500917 10.96426 -14.91772 16.38107
## 390      0.7316728 -9.502009 10.96535 -14.91939 16.38274
## 391      0.7316728 -9.503100 10.96645 -14.92106 16.38441
## 392      0.7316728 -9.504192 10.96754 -14.92273 16.38608
## 393      0.7316728 -9.505283 10.96863 -14.92440 16.38775
## 394      0.7316728 -9.506374 10.96972 -14.92607 16.38941

5.6.2 Plot

data.ramalan_meta.da <- ramalan_meta.da$mean
plot(ramalan_meta.da, xlab="Periode (Tahun)", col = "dodgerblue3", lwd = 2.5)

Berdasarkan hasil plot ramalan di atas, dapat dilihat bahwa ramalan ARIMA(0,1,1) cenderung stabil hingga akhir periode. Selanjutnya, dapat dicari nilai akurasi antara hasil ramalan dengan data uji sebagai berikut.

pt_1 <- train_meta.ts[length(train_meta.ts)] #nilai akhir data latih
hasil.forc.Diff <- data.ramalan_meta.da
ramal_meta <- diffinv(hasil.forc.Diff, differences = 1) + pt_1
#has.1 sama hasilnta dengan: cumsum(c(pt_1,hasil.forc.Diff))
ts.plot(train_meta.ts, ramal_meta, xlab="Periode (Hari)", 
        col = "dodgerblue3", lwd = 3.5,
        ylab="Saham Harga (USD)",
        main="Plot Ramalan Saham META Selama 79 Hari Kedepan")

Dapat dilihat bahwa rata-rata harga saham META diramalkan akan terus menaik setiap periodenya.

5.6.3 Perbandingan

perbandingan_meta.da <- matrix(data=c(head(test_meta.ts, n=h), ramal_meta[-1]),
                     nrow = h, ncol = 2)
colnames(perbandingan_meta.da) <- c("Aktual","Hasil Forecast")
datatable(perbandingan_meta.da, filter = 'top', 
          options = list(pageLength = 5))
akurasi.meta <- accuracy(ts(ramal_meta[-1]), head(test_meta.ts, n=h)) %>%
  as.data.frame() %>%
  cbind(Model = ramalan_meta.da[["method"]]) %>% 
  relocate(Model, .before = 1)
row.names(akurasi.meta) <- "META"
datatable(akurasi.meta)

Didapatkan nilai MAPE sebesar \(4.507078\%\) (kurang dari \(10\%\)) yang menandakan bahwa hasil peramalan dari model ARIMA(0,1,1) sudah sangat baik.

6 Microsoft

6.1 Uji Stasioner Data

6.1.1 Plot ACF

acf(train_msft.ts)

Berdasarkan plot ACF, terlihat bahwa plot ACF data train menurun secara perlahan (tails of slowly). Hal ini juga menjadi indikasi bahwa data tidak stasioner dalam rataan dan tidak membentuk gelombang sinus.

6.1.2 Uji ADF

tseries::adf.test(train_msft.ts)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  train_msft.ts
## Dickey-Fuller = -1.7147, Lag order = 6, p-value = 0.6967
## alternative hypothesis: stationary

\(H_0\) : Data tidak stasioner dalam rataan

\(H_1\) : Data stasioner dalam rataan

Berdasarkan uji ADF tersebut, didapat p-value sebesar \(0.6967\) yang lebih besar dari taraf nyata \(5\%\) sehingga tak tolak \(H_0\) dan menandakan bahwa data tidak stasioner dalam rataan. Hal ini sesuai dengan hasil eksplorasi menggunakan plot time series dan plot ACF, sehingga ketidakstasioneran model kedepannya harus ditangani.

6.1.3 Plot Box-Cox

index <- seq(1:nrow(msft))
bc = boxcox(msft.ts~index, lambda = seq(-2, 4, by=0.01))

#Nilai Rounded Lambda
lambda_msft <- bc$x[which.max(bc$y)]
#SK
sk_msft <- bc$x[bc$y > max(bc$y) - 1/2 * qchisq(.95,1)]
cat(" Lambda :", lambda_msft,
    "\n\n Selang Kepercyaan 95% \n",
    "Batas Bawah :", min(sk_msft), "\n Batas Atas  :", max(sk_msft) )
##  Lambda : -0.92 
## 
##  Selang Kepercyaan 95% 
##  Batas Bawah : -1.8 
##  Batas Atas  : -0.03

Gambar di atas menunjukkan nilai rounded value (\(\lambda\)) optimum sebesar \(-0.92\) dan pada selang kepercayaan \(95\%\) nilai memiliki batas bawah \(-1.8\) dan batas atas \(-0.03\). Selang tersebut tidak memuat nilai satu sehingga dapat dikatakan bahwa data saham amazon tidak stasioner dalam ragam.

6.1.4 Penanganan Ketidakstasioneran Data

train_msft.diff <- diff(train_msft.ts, differences = 1) 
plot.ts(train_msft.diff, lty=1, xlab="Periode (Tahun)", 
        col = "deepskyblue2", lwd = 3.5,
        main="Plot Difference Saham Microsoft")

Berdasarkan plot data deret waktu, terlihat bahwa data sudah stasioner dalam rataan ditandai dengan data bergerak pada nilai tengah tertentu (tidak terdapat trend ataupun musiman pada data).

6.2 Uji Ulang

6.2.1 Plot ACF

acf(train_msft.diff)

Berdasarkan plot ACF tersebut, terlihat bahwa tidak ada satupun lag yang cut off. Sejalan dengan penanganannya, data sudah stasioner dalam rataan dan ketidakstasioneran data telah berhasil tertangani.

6.2.2 Uji ADF

tseries::adf.test(train_msft.diff)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  train_msft.diff
## Dickey-Fuller = -7.044, Lag order = 6, p-value = 0.01
## alternative hypothesis: stationary

\(H_0\) : Data tidak stasioner dalam rataan

\(H_1\) : Data stasioner dalam rataan

Berdasarkan uji ADF tersebut, didapat p-value sebesar \(0.01\) yang lebih kecil dari taraf nyata \(5\%\) sehingga tolak \(H_0\) atau data stasioner dalam rataan. Hal ini sesuai dengan hasil eksplorasi menggunakan plot time series dan plot ACF, sehingga dalam hal ini ketidakstasioneran data sudah berhasil ditangani dan dapat dilanjutkan ke pemodelan.

6.3 Identifikasi Model

6.3.1 Plot ACF

acf(train_msft.diff)

Berdasarkan plot ACF tersebut, terlihat bahwa tidak ada satupun lag yang cut off. Maka model tidak dapat di identifikasi dengan plot ACF.

6.3.2 Plot PACF

pacf(train_msft.diff)

Berdasarkan plot PACF tersebut, terlihat bahwa tidak ada satupun lag yang cut off. Maka model tidak dapat di identifikasi dengan plot PACF.

6.3.3 Plot EACF

eacf(train_msft.diff)
## AR/MA
##   0 1 2 3 4 5 6 7 8 9 10 11 12 13
## 0 o o o o o o o o o o o  o  o  o 
## 1 o o o o o o o o o o o  o  o  o 
## 2 x x o o o o o o o o o  o  o  o 
## 3 x x x o o o o o o o o  o  o  o 
## 4 x x o x o o o o o o o  o  o  o 
## 5 x x o x x o o o o o o  o  o  o 
## 6 x x x o x o o o o o o  o  o  o 
## 7 x x x o x o o o o o o  o  o  o

Identifikasi model menggunakan plot EACF dilakukan dengan melihat titik sudut kiri segitiga pada pola segitiga nol atas (pola mariks segitiga bawah). Dalam hal ini model tentatif yang terbentuk adalah ARIMA(0,1,1), ARIMA(1,1,1), ARIMA(2,1,2), dst.. Namun karena kemungkinannya sangat banyak, maka akan digunakan function agar menyingkat proses.

6.4 Pendugaan Parameter Model Tentatif

model.tentaif_msft <- 
  model_tentatif(train_msft.diff, p_max = 6, d = 1, q_max = 12)
## AR/MA
##   0 1 2 3 4 5 6 7 8 9 10 11 12 13
## 0 o o o o o o o o o o o  o  o  o 
## 1 o o o o o o o o o o o  o  o  o 
## 2 x x o o o o o o o o o  o  o  o 
## 3 x x x o o o o o o o o  o  o  o 
## 4 x x o x o o o o o o o  o  o  o 
## 5 x x o x x o o o o o o  o  o  o 
## 6 x x x o x o o o o o o  o  o  o 
## 7 x x x o x o o o o o o  o  o  o 
## 
## Model ARIMA dengan AIC terkecil:
## Series: data 
## ARIMA(2,1,3) 
## 
## Coefficients:
##          ar1      ar2      ma1     ma2      ma3
##       0.0868  -0.9752  -1.0458  1.0498  -0.9944
## s.e.  0.0181   0.0167   0.0198  0.0322   0.0315
## 
## sigma^2 = 31.4:  log likelihood = -985.19
## AIC=1982.37   AICc=1982.65   BIC=2004.85
datatable(model.tentaif_msft, filter = 'top', 
          options = list(pageLength = 5))

Berdasarkan pendugaan parameter di atas, nilai AIC terkecil \(1982.37\) dimiliki oleh model ARIMA(2,1,3) dan seluruh parameternya signifikan sehingga model yang dipilih adalah model ARIMA(2,1,3).

model_msft.da <- Arima(train_msft.diff, order=c(2,1,3), method="ML")

6.5 Analisis Sisaan

Model terbaik hasil identifikasi kemudian dicek asumsi sisaannya. Sisaan model ARIMA harus memenuhi asumsi normalitas, kebebasan sisaan, dan kehomogenan ragam. Diagnostik model dilakukan secara eksplorasi dan uji formal.

6.5.1 Eksplorasi Sisaan

#Eksplorasi 
sisaan_msft.da <- model_msft.da$residuals 
par(mfrow=c(2,2)) 
# QQ-Plot
qqnorm(sisaan_msft.da) 
qqline(sisaan_msft.da, col = "dodgerblue3", lwd = 2.5) 
# Plot sisaan
plot(c(1:length(sisaan_msft.da)), sisaan_msft.da, 
     main = "Plot Sisaan Model ARIMA",
     xlab = "Periode",
     ylab = "Nilai Sisaan")
abline(h = 0, col = "firebrick2", lty = 2, lwd=2.5)
#Plot ACF dan PACF
acf(sisaan_msft.da) 
pacf(sisaan_msft.da) 

Berdasarkan plot kuantil-kuantil normal, secara eksplorasi ditunjukkan sisaan menyebar normal ditandai dengan titik titik yang cenderung mengikuti garis \(45^{\circ}\). Kemudian dapat dilihat juga lebar pita sisaan yang cenderung sama menandakan bahwa sisaan memiliki ragam yang homogen. Plot ACF dan PACF sisaan ARIMA(2,1,3) juga tidak signifikan pada 20 lag awal yang menandakan saling bebas. Kondisi ini akan diuji lebih lanjut dengan uji formal.

6.5.2 Uji Formal

6.5.2.1 Sisaan Menyebar Normal

ks.test(sisaan_msft.da,"pnorm")  #tak tolak H0 > sisaan menyebar normal
## 
##  Asymptotic one-sample Kolmogorov-Smirnov test
## 
## data:  sisaan_msft.da
## D = 0.34997, p-value < 2.2e-16
## alternative hypothesis: two-sided

Selain dengan eksplorasi, asumsi tersebut dapat diuji menggunakan uji formal. Pada tahapan ini uji formal yang digunakan untuk normalitas adalah uji Kolmogorov-Smirnov (KS). Hipotesis pada uji KS adalah sebagai berikut.

\(H_0\) : Sisaan menyebar normal

\(H_1\) : Sisaan tidak menyebar normal

Berdasarkan uji KS tersebut, didapat p-value sebesar \(2.2\times 10^{-16}\) yang kurang dari taraf nyata \(5\%\) sehingga tolak \(H_0\) dan menandakan bahwa sisaan tidak menyebar normal. Hal ini sesuai dengan hasil eksplorasi menggunakan plot kuantil-kuantil normal.

6.5.2.2 Sisaan saling bebas/tidak ada autokorelasi

Box.test(sisaan_msft.da, type = "Ljung")  #tak tolak H0 > sisaan saling bebas
## 
##  Box-Ljung test
## 
## data:  sisaan_msft.da
## X-squared = 0.6198, df = 1, p-value = 0.4311

Selanjutnya akan dilakukan uji formal untuk kebebasan sisaan menggunakan uji Ljung-Box. Hipotesis yang digunakan adalah sebagai berikut.

\(H_0\) : Sisaan saling bebas

\(H_1\) : Sisaan tidak tidak saling bebas

Berdasarkan uji Ljung-Box tersebut, didapat p-value sebesar \(0.4311\) yang lebih besar dari taraf nyata \(5\%\) sehingga tak tolak \(H_0\) dan menandakan bahwa sisaan saling bebas. Hal ini sesuai dengan hasil eksplorasi menggunakan plot ACF dan PACF.

6.5.2.3 Sisaan homogen

Box.test((sisaan_msft.da)^2, type = "Ljung")  #tak tolak H0 > sisaan homogen
## 
##  Box-Ljung test
## 
## data:  (sisaan_msft.da)^2
## X-squared = 0.66346, df = 1, p-value = 0.4153

Hipotesis yang digunakan untuk uji kehomogenan ragam adalah sebagai berikut.

\(H_0\) : Ragam sisaan homogen

\(H_1\) : Ragam sisaan tidak homogen

Berdasarkan uji Ljung-Box terhadap sisaan kuadrat tersebut, didapat p-value sebesar \(0.4153\) yang lebih besar dari taraf nyata \(5\%\) sehingga tolak \(H_0\) dan menandakan bahwa ragam sisaan homogen.

6.5.2.4 Nilai tengah sama dengan nol

#4) Nilai tengah sisaan sama dengan nol 
t.test(sisaan_msft.da, mu = 0, conf.level = 0.95)  #tak tolak h0 > nilai tengah sisaan sama dengan 0
## 
##  One Sample t-test
## 
## data:  sisaan_msft.da
## t = 1.6763, df = 313, p-value = 0.09468
## alternative hypothesis: true mean is not equal to 0
## 95 percent confidence interval:
##  -0.09096971  1.13800932
## sample estimates:
## mean of x 
## 0.5235198

Terakhir, dengan uji-t, akan dicek apakah nilai tengah sisaan sama dengan nol. Hipotesis yang diujikan sebagai berikut.

\(H_0\) : nilai tengah sisaan sama dengan 0

\(H_1\) : nilai tengah sisaan tidak sama dengan 0

Berdasarkan uji-ttersebut, didapat p-value sebesar \(0.09468\) yang lebih besar dari taraf nyata \(5\%\) sehingga tak tolak \(H_0\) dan menandakan bahwa nilai tengah sisaan sama dengan nol.

6.6 Peramalan

6.6.1 Ramal

Peramalan dilakukan menggunakan fungsi forecast() . Contoh peramalan berikut ini dilakukan untuk h hari ke depan.

#---FORECAST---#
ramalan_msft.da <- forecast::forecast(model_msft.da, h = h) 
ramalan_msft.da
##     Point Forecast     Lo 80    Hi 80      Lo 95     Hi 95
## 316  -1.5554200350 -8.756031 5.645191 -12.567804  9.456964
## 317   0.3403917731 -6.866442 7.547226 -10.681509 11.362293
## 318   1.5592699640 -5.650366 8.768906  -9.466917 12.585457
## 319  -0.1836752425 -7.396019 7.028669 -11.214004 10.846653
## 320  -1.5235394112 -8.737019 5.689940 -12.555604  9.508525
## 321   0.0598363676 -7.158226 7.277898 -10.979237 11.098910
## 322   1.5038334270 -5.717969 8.725636  -9.540961 12.548627
## 323   0.0851008399 -7.138353 7.308555 -10.962219 11.132421
## 324  -1.4461542906 -8.671313 5.779005 -12.496082  9.603773
## 325  -0.1955481731 -7.423809 7.032713 -11.250219 10.859123
## 326   1.4062070451 -5.826540 8.638954  -9.655324 12.467738
## 327   0.3256698324 -6.907901 7.559240 -10.737121 11.388461
## 328  -1.3300751450 -8.565788 5.905638 -12.396144  9.735993
## 329  -0.4200681930 -7.657655 6.817519 -11.489002 10.648866
## 330   1.2735262533 -5.969021 8.516073  -9.802994 12.350046
## 331   0.5330987381 -6.709726 7.775923 -10.543846 11.610043
## 332  -1.1826882886 -8.427902 6.062526 -12.263287  9.897910
## 333  -0.6095542333 -7.855715 6.636607 -11.691601 10.472492
## 334   1.1133557506 -6.137938 8.364649  -9.976541 12.203252
## 335   0.7039781527 -6.547339 7.955296 -10.385955 11.793911
## 336  -1.0116664137 -8.265411 6.242078 -12.105311 10.081978
## 337  -0.7613474390 -8.015421 6.492726 -11.855496 10.332801
## 338   0.9334084046 -6.325677 8.192494 -10.168405 12.035221
## 339   0.8363846153 -6.422739 8.095508 -10.265487 11.938256
## 340  -0.8246977448 -8.086092 6.436696 -11.930042 10.280646
## 341  -0.8742393387 -8.135629 6.387151 -11.979577 10.231098
## 342   0.7412863594 -6.524741 8.007314 -10.371144 11.853716
## 343   0.9297994153 -6.336497 8.196095 -10.183041 12.042640
## 344  -0.6292406231 -7.897500 6.639018 -11.745083 10.486602
## 345  -0.9483713709 -8.216525 6.319782 -12.064053 10.167310
## 346   0.5442504342 -6.727976 7.816477 -10.577660 11.666161
## 347   0.9849906016 -6.287882 8.257863 -10.137909 12.107890
## 348  -0.4323088725 -7.706743 6.842125 -11.557595 10.692977
## 349  -0.9851011966 -8.259496 6.289294 -12.110328 10.140126
## 350   0.3490224234 -6.928764 7.626809 -10.781392 11.479436
## 351   1.0038654594 -6.275018 8.282749 -10.128226 12.135956
## 352  -0.2402918122 -7.520301 7.039717 -11.374105 10.893521
## 353  -0.9868432199 -8.266980 6.293294 -12.120852 10.147165
## 354   0.1616234192 -7.121180 7.444427 -10.976463 11.299710
## 355   0.9893009599 -6.295051 8.273653 -10.151154 12.129756
## 356  -0.0588113098 -7.343879 7.226256 -11.200361 11.082738
## 357  -0.9568908438 -8.242289 6.328508 -12.098946 10.185165
## 358  -0.0127501595 -7.300113 7.274612 -11.157809 11.132309
## 359   0.9449596726 -6.344346 8.234265 -10.203071 12.092991
## 360   0.1073831350 -7.182298 7.397065 -11.041223 11.255989
## 361  -0.8992278496 -8.189428 6.390973 -12.048628 10.250172
## 362  -0.1698125077 -7.461349 7.121724 -11.321255 10.981630
## 363   0.8750983712 -6.418674 8.168871 -10.279764 12.029961
## 364   0.2544815865 -7.039429 7.548392 -10.900592 11.409555
## 365  -0.8183359250 -8.112903 6.476231 -11.974414 10.337742
## 366  -0.3062372586 -7.601621 6.989146 -11.463563 10.851089
## 367   0.7843761048 -6.513410 8.082162 -10.376624 11.945377
## 368   0.3796446281 -6.918157 7.677446 -10.781380 11.540669
## 369  -0.7190048160 -8.017531 6.579522 -11.881138 10.443128
## 370  -0.4196711937 -7.718620 6.879277 -11.582450 10.743107
## 371   0.6776678758 -6.623716 7.979052 -10.488835 11.844171
## 372   0.4810005622 -6.820391 7.782392 -10.685514 11.647515
## 373  -0.6061508752 -7.908261 6.695959 -11.773765 10.561463
## 374  -0.5087157649 -7.810980 6.793549 -11.676566 10.659134
## 375   0.5598892984 -6.744719 7.864497 -10.611545 11.731323
## 376   0.5576121746 -6.747093 7.862318 -10.613971 11.729195
## 377  -0.4846489604 -7.790003 6.820705 -11.657224 10.687926
## 378  -0.5728800963 -7.878234 6.732474 -11.745455 10.599695
## 379   0.4358367509 -6.871665 7.743339 -10.740023 11.611697
## 380   0.6094170308 -6.698346 7.917181 -10.566843 11.785677
## 381  -0.3591817379 -7.667477 6.949113 -11.536255 10.817891
## 382  -0.6125096853 -7.920743 6.695723 -11.789487 10.564468
## 383   0.3100466101 -7.000063 7.620156 -10.869801 11.489894
## 384   0.6371457324 -6.673433 7.947725 -10.543420 11.817711
## 385  -0.2341095070 -7.545079 7.076860 -11.415272 10.947053
## 386  -0.6286953916 -7.939606 6.682216 -11.809769 10.552378
## 387   0.1866762067 -7.125796 7.499149 -10.996786 11.370138
## 388   0.6422228350 -6.670940 7.955386 -10.542295 11.826740
## 389  -0.1133627121 -7.426774 7.200049 -11.298260 11.071535
## 390  -0.6231674886 -7.936564 6.690229 -11.808042 10.561707
## 391   0.0694082021 -7.245221 7.384038 -11.117353 11.256169
## 392   0.6266552326 -6.688871 7.942181 -10.561476 11.814787
## 393  -0.0003583796 -7.316010 7.315294 -11.188683 11.187966
## 394  -0.5981795675 -7.913875 6.717516 -11.786571 10.590211

6.6.2 Plot

data.ramalan_msft.da <- ramalan_msft.da$mean
plot(ramalan_msft.da, xlab="Periode (Tahun)", col = "deepskyblue2", lwd = 2.5)

Berdasarkan hasil plot ramalan di atas, dapat dilihat bahwa ramalan ARIMA(4,1,5) cenderung stabil hingga akhir periode. Selanjutnya, dapat dicari nilai akurasi antara hasil ramalan dengan data uji sebagai berikut.

pt_1 <- train_msft.ts[length(train_msft.ts)] #nilai akhir data latih
hasil.forc.Diff <- data.ramalan_msft.da
ramal_msft <- diffinv(hasil.forc.Diff, differences = 1) + pt_1
#has.1 sama hasilnta dengan: cumsum(c(pt_1,hasil.forc.Diff))
ts.plot(train_msft.ts, ramal_msft, xlab="Periode (Hari)", 
        ylab="Saham Harga (USD)",
        col = "deepskyblue2", lwd = 3.5,
        main="Plot Ramalan Saham Microsoft Selama 79 Hari Kedepan")

Dapat dilihat bahwa rata-rata harga saham Microsoft diramalkan akan terus konstan setiap periodenya.

6.6.3 Perbandingan

perbandingan_msft.da <- matrix(data=c(head(test_msft.ts, n=h), ramal_msft[-1]),
                     nrow = h, ncol = 2)
colnames(perbandingan_msft.da) <- c("Aktual","Hasil Forecast")
datatable(perbandingan_msft.da, filter = 'top', 
          options = list(pageLength = 5))
akurasi.msft <- accuracy(ts(ramal_msft[-1]), head(test_msft.ts, n=h)) %>%
  as.data.frame() %>%
  cbind(Model = ramalan_msft.da[["method"]]) %>% 
  relocate(Model, .before = 1)
row.names(akurasi.msft) <- "MSFT"
akurasi.msft
##             Model       ME     RMSE      MAE     MPE     MAPE      ACF1
## MSFT ARIMA(2,1,3) 34.47045 40.46354 35.15531 10.3402 10.58501 0.9433182
##      Theil's U
## MSFT  6.979381

Didapatkan nilai MAPE sebesar \(7.869212\%\) (kurang dari \(10\%\)) yang menandakan bahwa hasil peramalan dari model ARIMA(2,1,3) sudah sangat baik.

7 Netflix

7.1 Uji Stasioner Data

7.1.1 Plot ACF

acf(train_nflx.ts)

Berdasarkan plot ACF, terlihat bahwa plot ACF data train menurun secara perlahan (tails of slowly). Hal ini juga menjadi indikasi bahwa data tidak stasioner dalam rataan dan tidak membentuk gelombang sinus.

7.1.2 Uji ADF

tseries::adf.test(train_nflx.ts)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  train_nflx.ts
## Dickey-Fuller = -2.9406, Lag order = 6, p-value = 0.1799
## alternative hypothesis: stationary

\(H_0\) : Data tidak stasioner dalam rataan

\(H_1\) : Data stasioner dalam rataan

Berdasarkan uji ADF tersebut, didapat p-value sebesar \(0.1799\) yang lebih besar dari taraf nyata \(5\%\) sehingga tak tolak \(H_0\) dan menandakan bahwa data tidak stasioner dalam rataan. Hal ini sesuai dengan hasil eksplorasi menggunakan plot time series dan plot ACF, sehingga ketidakstasioneran model kedepannya harus ditangani.

7.1.3 Plot Box-Cox

index <- seq(1:nrow(nflx))
bc = boxcox(nflx.ts~index, lambda = seq(-2, 4, by=0.01))

#Nilai Rounded Lambda
lambda_nflx <- bc$x[which.max(bc$y)]
#SK
sk_nflx <- bc$x[bc$y > max(bc$y) - 1/2 * qchisq(.95,1)]
cat(" Lambda :", lambda_nflx,
    "\n\n Selang Kepercyaan 95% \n",
    "Batas Bawah :", min(sk_nflx), "\n Batas Atas  :", max(sk_nflx) )
##  Lambda : 0.19 
## 
##  Selang Kepercyaan 95% 
##  Batas Bawah : -0.14 
##  Batas Atas  : 0.51

Gambar di atas menunjukkan nilai rounded value (\(\lambda\)) optimum sebesar \(0.19\) dan pada selang kepercayaan \(95\%\) nilai memiliki batas bawah \(-0.14\) dan batas atas \(0.51\). Selang tersebut tidak memuat nilai satu sehingga dapat dikatakan bahwa data saham amazon tidak stasioner dalam ragam.

7.1.4 Penanganan Ketidakstasioneran Data

train_nflx.diff <- diff(train_nflx.ts, differences = 1) 
plot.ts(train_nflx.diff, lty=1, xlab="Periode (Hari)", 
        col = "firebrick3", lwd = 3.5,
        main="Plot Difference Saham Netflix")

Berdasarkan plot data deret waktu, terlihat bahwa data sudah stasioner dalam rataan ditandai dengan data bergerak pada nilai tengah tertentu (tidak terdapat trend ataupun musiman pada data).

7.2 Uji Ulang

7.2.1 Plot ACF

acf(train_nflx.diff)

Berdasarkan plot tersebut, terlihat bahwa plot ACF cuts off pada lag ke 23. Sejalan dengan penanganannya, data sudah stasioner dalam rataan dan ketidakstasioneran data telah berhasil tertangani.

7.2.2 Uji ADF

tseries::adf.test(train_nflx.diff)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  train_nflx.diff
## Dickey-Fuller = -7.1658, Lag order = 6, p-value = 0.01
## alternative hypothesis: stationary

\(H_0\) : Data tidak stasioner dalam rataan

\(H_1\) : Data stasioner dalam rataan

Berdasarkan uji ADF tersebut, didapat p-value sebesar \(0.01\) yang lebih kecil dari taraf nyata \(5\%\) sehingga tolak \(H_0\) atau data stasioner dalam rataan. Hal ini sesuai dengan hasil eksplorasi menggunakan plot time series dan plot ACF, sehingga dalam hal ini ketidakstasioneran data sudah berhasil ditangani dan dapat dilanjutkan ke pemodelan.

7.3 Identifikasi Model

7.3.1 Plot ACF

acf(train_nflx.diff)

Berdasarkan plot tersebut, terlihat bahwa plot ACF cenderung cuts off pada lag ke 23. Maka model tidak dapat di identifikasi dengan plot ACF.

7.3.2 Plot PACF

pacf(train_nflx.diff)

Berdasarkan plot tersebut, terlihat bahwa plot PACF cenderung cuts off pada lag ke 23. Maka model tidak dapat di identifikasi dengan plot PACF.

7.3.3 Plot EACF

eacf(train_nflx.diff)
## AR/MA
##   0 1 2 3 4 5 6 7 8 9 10 11 12 13
## 0 o o o o o o o o o o o  o  o  o 
## 1 x o o o o o o o o o o  o  o  o 
## 2 x o o o o o o o o o o  o  o  o 
## 3 x x x o o o o o o o o  o  o  o 
## 4 x x o x o o o o o o o  o  o  o 
## 5 x x o o x o o o o o o  o  o  o 
## 6 x x x o x x o o o o o  o  o  o 
## 7 x o x x x x o o o o o  o  o  o

Identifikasi model menggunakan plot EACF dilakukan dengan melihat titik sudut kiri segitiga pada pola segitiga nol atas (pola mariks segitiga bawah). Dalam hal ini model tentatif yang terbentuk adalah ARIMA(0,1,1), ARIMA(1,1,1), ARIMA(2,1,2), dst.. Namun karena kemungkinannya sangat banyak, maka akan digunakan function agar menyingkat proses.

7.4 Pendugaan Parameter Model Tentatif

model.tentaif_nflx <- 
  model_tentatif(train_nflx.diff, p_max = 6, d = 1, q_max = 12)
## AR/MA
##   0 1 2 3 4 5 6 7 8 9 10 11 12 13
## 0 o o o o o o o o o o o  o  o  o 
## 1 x o o o o o o o o o o  o  o  o 
## 2 x o o o o o o o o o o  o  o  o 
## 3 x x x o o o o o o o o  o  o  o 
## 4 x x o x o o o o o o o  o  o  o 
## 5 x x o o x o o o o o o  o  o  o 
## 6 x x x o x x o o o o o  o  o  o 
## 7 x o x x x x o o o o o  o  o  o 
## 
## Model ARIMA dengan AIC terkecil:
## Series: data 
## ARIMA(0,1,1) 
## 
## Coefficients:
##           ma1
##       -0.9796
## s.e.   0.0120
## 
## sigma^2 = 178.2:  log likelihood = -1256.36
## AIC=2516.73   AICc=2516.77   BIC=2524.22
datatable(model.tentaif_nflx, filter = 'top', 
          options = list(pageLength = 5))

Berdasarkan pendugaan parameter di atas, nilai AIC terkecil \(2516.73\) dimiliki oleh model ARIMA(0,1,1) dan seluruh parameternya signifikan sehingga model yang dipilih adalah model ARIMA(0,1,1).

model_nflx.da <- Arima(train_nflx.diff, order=c(0,1,1), method="ML")

7.5 Analisis Sisaan

Model terbaik hasil identifikasi kemudian dicek asumsi sisaannya. Sisaan model ARIMA harus memenuhi asumsi normalitas, kebebasan sisaan, dan kehomogenan ragam. Diagnostik model dilakukan secara eksplorasi dan uji formal.

7.5.1 Eksplorasi Sisaan

#Eksplorasi 
sisaan_nflx.da <- model_nflx.da$residuals 
par(mfrow=c(2,2)) 
# QQ-Plot
qqnorm(sisaan_nflx.da) 
qqline(sisaan_nflx.da, col = "dodgerblue3", lwd = 2.5) 
# Plot sisaan
plot(c(1:length(sisaan_nflx.da)), sisaan_nflx.da, 
     main = "Plot Sisaan Model ARIMA",
     xlab = "Periode",
     ylab = "Nilai Sisaan")
abline(h = 0, col = "firebrick2", lty = 2, lwd=2.5)
#Plot ACF dan PACF
acf(sisaan_nflx.da) 
pacf(sisaan_nflx.da) 

Berdasarkan plot kuantil-kuantil normal, secara eksplorasi ditunjukkan sisaan tidak menyebar normal ditandai dengan tidak semua titik (ada pencilan) mengikuti garis \(45^{\circ}\). Kemudian dapat dilihat juga lebar pita sisaan yang cenderung tidak sama dikarenakan adanya pencilan menandakan bahwa sisaan memiliki ragam yang tidak homogen. Plot ACF dan PACF sisaan ARIMA(0,1,1) juga signifikan pada 20 lag awal yang menandakan tidak saling bebas. Kondisi ini akan diuji lebih lanjut dengan uji formal.

7.5.2 Uji Formal

7.5.2.1 Sisaan Menyebar Normal

ks.test(sisaan_nflx.da,"pnorm")  #tak tolak H0 > sisaan menyebar normal
## 
##  Asymptotic one-sample Kolmogorov-Smirnov test
## 
## data:  sisaan_nflx.da
## D = 0.41196, p-value < 2.2e-16
## alternative hypothesis: two-sided

Selain dengan eksplorasi, asumsi tersebut dapat diuji menggunakan uji formal. Pada tahapan ini uji formal yang digunakan untuk normalitas adalah uji Kolmogorov-Smirnov (KS). Hipotesis pada uji KS adalah sebagai berikut.

\(H_0\) : Sisaan menyebar normal

\(H_1\) : Sisaan tidak menyebar normal

Berdasarkan uji KS tersebut, didapat p-value sebesar \(2.2\times 10^{-16}\) yang kurang dari taraf nyata \(5\%\) sehingga tolak \(H_0\) dan menandakan bahwa sisaan tidak menyebar normal. Hal ini sesuai dengan hasil eksplorasi menggunakan plot kuantil-kuantil normal.

7.5.2.2 Sisaan saling bebas/tidak ada autokorelasi

Box.test(sisaan_nflx.da, type = "Ljung")  #tak tolak H0 > sisaan saling bebas
## 
##  Box-Ljung test
## 
## data:  sisaan_nflx.da
## X-squared = 0.27276, df = 1, p-value = 0.6015

Selanjutnya akan dilakukan uji formal untuk kebebasan sisaan menggunakan uji Ljung-Box. Hipotesis yang digunakan adalah sebagai berikut.

\(H_0\) : Sisaan saling bebas

\(H_1\) : Sisaan tidak tidak saling bebas

Berdasarkan uji Ljung-Box tersebut, didapat p-value sebesar \(0.6015\) yang lebih besar dari taraf nyata \(5\%\) sehingga tak tolak \(H_0\) dan menandakan bahwa sisaan saling bebas.

7.5.2.3 Sisaan homogen

Box.test((sisaan_nflx.da)^2, type = "Ljung")  #tak tolak H0 > sisaan homogen
## 
##  Box-Ljung test
## 
## data:  (sisaan_nflx.da)^2
## X-squared = 0.00065819, df = 1, p-value = 0.9795

Hipotesis yang digunakan untuk uji kehomogenan ragam adalah sebagai berikut.

\(H_0\) : Ragam sisaan homogen

\(H_1\) : Ragam sisaan tidak homogen

Berdasarkan uji Ljung-Box terhadap sisaan kuadrat tersebut, didapat p-value sebesar \(0.9795\) yang lebih besar dari taraf nyata \(5\%\) sehingga tak tolak \(H_0\) dan menandakan bahwa ragam sisaan homogen.

7.5.2.4 Nilai tengah sama dengan nol

#4) Nilai tengah sisaan sama dengan nol 
t.test(sisaan_nflx.da, mu = 0, conf.level = 0.95)  #tak tolak h0 > nilai tengah sisaan sama dengan 0
## 
##  One Sample t-test
## 
## data:  sisaan_nflx.da
## t = 1.709, df = 313, p-value = 0.08844
## alternative hypothesis: true mean is not equal to 0
## 95 percent confidence interval:
##  -0.1935852  2.7525293
## sample estimates:
## mean of x 
##  1.279472

Terakhir, dengan uji-t, akan dicek apakah nilai tengah sisaan sama dengan nol. Hipotesis yang diujikan sebagai berikut.

\(H_0\) : nilai tengah sisaan sama dengan 0

\(H_1\) : nilai tengah sisaan tidak sama dengan 0

Berdasarkan uji-ttersebut, didapat p-value sebesar \(0.08844\) yang lebih besar dari taraf nyata \(5\%\) sehingga tak tolak \(H_0\) dan menandakan bahwa nilai tengah sisaan sama dengan nol.

7.6 Peramalan

7.6.1 Ramal

Peramalan dilakukan menggunakan fungsi forecast() . Contoh peramalan berikut ini dilakukan untuk h hari ke depan.

#---FORECAST---#
ramalan_nflx.da <- forecast::forecast(model_nflx.da, h = h) 
ramalan_nflx.da
##     Point Forecast     Lo 80    Hi 80     Lo 95    Hi 95
## 316      0.6704789 -16.43762 17.77857 -25.49409 26.83505
## 317      0.6704789 -16.44118 17.78214 -25.49954 26.84050
## 318      0.6704789 -16.44474 17.78570 -25.50499 26.84595
## 319      0.6704789 -16.44830 17.78926 -25.51044 26.85140
## 320      0.6704789 -16.45187 17.79282 -25.51589 26.85685
## 321      0.6704789 -16.45543 17.79638 -25.52133 26.86229
## 322      0.6704789 -16.45899 17.79994 -25.52678 26.86774
## 323      0.6704789 -16.46255 17.80350 -25.53222 26.87318
## 324      0.6704789 -16.46610 17.80706 -25.53766 26.87862
## 325      0.6704789 -16.46966 17.81062 -25.54310 26.88406
## 326      0.6704789 -16.47322 17.81418 -25.54854 26.88950
## 327      0.6704789 -16.47677 17.81773 -25.55398 26.89494
## 328      0.6704789 -16.48033 17.82129 -25.55942 26.90038
## 329      0.6704789 -16.48388 17.82484 -25.56486 26.90581
## 330      0.6704789 -16.48744 17.82840 -25.57029 26.91125
## 331      0.6704789 -16.49099 17.83195 -25.57573 26.91668
## 332      0.6704789 -16.49454 17.83550 -25.58116 26.92212
## 333      0.6704789 -16.49810 17.83905 -25.58659 26.92755
## 334      0.6704789 -16.50165 17.84260 -25.59202 26.93298
## 335      0.6704789 -16.50520 17.84616 -25.59745 26.93841
## 336      0.6704789 -16.50875 17.84970 -25.60288 26.94384
## 337      0.6704789 -16.51230 17.85325 -25.60831 26.94927
## 338      0.6704789 -16.51584 17.85680 -25.61373 26.95469
## 339      0.6704789 -16.51939 17.86035 -25.61916 26.96012
## 340      0.6704789 -16.52294 17.86390 -25.62458 26.96554
## 341      0.6704789 -16.52648 17.86744 -25.63001 26.97096
## 342      0.6704789 -16.53003 17.87099 -25.63543 26.97639
## 343      0.6704789 -16.53357 17.87453 -25.64085 26.98181
## 344      0.6704789 -16.53712 17.87807 -25.64627 26.98723
## 345      0.6704789 -16.54066 17.88162 -25.65169 26.99264
## 346      0.6704789 -16.54420 17.88516 -25.65710 26.99806
## 347      0.6704789 -16.54774 17.88870 -25.66252 27.00348
## 348      0.6704789 -16.55128 17.89224 -25.66794 27.00889
## 349      0.6704789 -16.55482 17.89578 -25.67335 27.01431
## 350      0.6704789 -16.55836 17.89932 -25.67876 27.01972
## 351      0.6704789 -16.56190 17.90286 -25.68417 27.02513
## 352      0.6704789 -16.56544 17.90640 -25.68959 27.03054
## 353      0.6704789 -16.56898 17.90994 -25.69499 27.03595
## 354      0.6704789 -16.57251 17.91347 -25.70040 27.04136
## 355      0.6704789 -16.57605 17.91701 -25.70581 27.04677
## 356      0.6704789 -16.57958 17.92054 -25.71122 27.05217
## 357      0.6704789 -16.58312 17.92408 -25.71662 27.05758
## 358      0.6704789 -16.58665 17.92761 -25.72203 27.06298
## 359      0.6704789 -16.59019 17.93114 -25.72743 27.06839
## 360      0.6704789 -16.59372 17.93468 -25.73283 27.07379
## 361      0.6704789 -16.59725 17.93821 -25.73823 27.07919
## 362      0.6704789 -16.60078 17.94174 -25.74363 27.08459
## 363      0.6704789 -16.60431 17.94527 -25.74903 27.08999
## 364      0.6704789 -16.60784 17.94880 -25.75443 27.09539
## 365      0.6704789 -16.61137 17.95233 -25.75982 27.10078
## 366      0.6704789 -16.61489 17.95585 -25.76522 27.10618
## 367      0.6704789 -16.61842 17.95938 -25.77061 27.11157
## 368      0.6704789 -16.62195 17.96291 -25.77601 27.11696
## 369      0.6704789 -16.62547 17.96643 -25.78140 27.12236
## 370      0.6704789 -16.62900 17.96996 -25.78679 27.12775
## 371      0.6704789 -16.63252 17.97348 -25.79218 27.13314
## 372      0.6704789 -16.63605 17.97700 -25.79757 27.13853
## 373      0.6704789 -16.63957 17.98053 -25.80296 27.14391
## 374      0.6704789 -16.64309 17.98405 -25.80834 27.14930
## 375      0.6704789 -16.64661 17.98757 -25.81373 27.15468
## 376      0.6704789 -16.65013 17.99109 -25.81911 27.16007
## 377      0.6704789 -16.65365 17.99461 -25.82449 27.16545
## 378      0.6704789 -16.65717 17.99813 -25.82988 27.17083
## 379      0.6704789 -16.66069 18.00165 -25.83526 27.17622
## 380      0.6704789 -16.66421 18.00517 -25.84064 27.18160
## 381      0.6704789 -16.66773 18.00868 -25.84602 27.18697
## 382      0.6704789 -16.67124 18.01220 -25.85139 27.19235
## 383      0.6704789 -16.67476 18.01572 -25.85677 27.19773
## 384      0.6704789 -16.67827 18.01923 -25.86215 27.20310
## 385      0.6704789 -16.68179 18.02274 -25.86752 27.20848
## 386      0.6704789 -16.68530 18.02626 -25.87289 27.21385
## 387      0.6704789 -16.68881 18.02977 -25.87827 27.21922
## 388      0.6704789 -16.69232 18.03328 -25.88364 27.22460
## 389      0.6704789 -16.69584 18.03679 -25.88901 27.22997
## 390      0.6704789 -16.69935 18.04030 -25.89438 27.23533
## 391      0.6704789 -16.70286 18.04381 -25.89974 27.24070
## 392      0.6704789 -16.70637 18.04732 -25.90511 27.24607
## 393      0.6704789 -16.70987 18.05083 -25.91048 27.25143
## 394      0.6704789 -16.71338 18.05434 -25.91584 27.25680

7.6.2 Plot

data.ramalan_nflx.da <- ramalan_nflx.da$mean
plot(ramalan_nflx.da, xlab="Periode (Hari)", col = "firebrick3", lwd = 2.5)

Berdasarkan hasil plot ramalan di atas, dapat dilihat bahwa ramalan ARIMA(``0,1,1``) cenderung stabil hingga akhir periode. Selanjutnya, dapat dicari nilai akurasi antara hasil ramalan dengan data uji sebagai berikut.

pt_1 <- train_nflx.ts[length(train_nflx.ts)] #nilai akhir data latih
hasil.forc.Diff <- data.ramalan_nflx.da
ramal_nflx <- diffinv(hasil.forc.Diff, differences = 1) + pt_1
#has.1 sama hasilnta dengan: cumsum(c(pt_1,hasil.forc.Diff))
ts.plot(train_nflx.ts, ramal_nflx, ylab="Saham Harga (USD)", 
        xlab="Periode (Hari)", 
        col = "firebrick3", lwd = 3.5,
        main="Plot Ramalan Saham Netflix Selama 79 Hari Kedepan")

Dapat dilihat bahwa rata-rata harga saham Netfilx diramalkan akan terus menaik setiap periodenya.

7.6.3 Perbandingan

perbandingan_nflx.da <- matrix(data=c(head(test_nflx.ts, n=h), ramal_nflx[-1]),
                     nrow = h, ncol = 2)
colnames(perbandingan_nflx.da) <- c("Aktual","Hasil Forecast")
datatable(perbandingan_nflx.da, filter = 'top', 
          options = list(pageLength = 5))
akurasi.nflx <- accuracy(ts(ramal_nflx[-1]), head(test_nflx.ts, n=h)) %>%
  as.data.frame() %>%
  cbind(Model = ramalan_nflx.da[["method"]]) %>% 
  relocate(Model, .before = 1)
row.names(akurasi.nflx) <- "NFLX"
akurasi.nflx
##             Model      ME     RMSE      MAE      MPE     MAPE      ACF1
## NFLX ARIMA(0,1,1) 12.6135 37.35304 33.12398 2.166506 8.381337 0.9631411
##      Theil's U
## NFLX  3.948959

Didapatkan nilai MAPE sebesar \(7.420446\%\) (kurang dari \(10\%\)) yang menandakan bahwa hasil peramalan dari model ARIMA(0,1,1) sudah sangat baik.

8 NVIDIA

8.1 Uji Stasioner Data

8.1.1 Plot ACF

acf(train_nvda.ts)

Berdasarkan plot ACF, terlihat bahwa plot ACF data train menurun secara perlahan (tails of slowly). Hal ini juga menjadi indikasi bahwa data tidak stasioner dalam rataan dan tidak membentuk gelombang sinus.

8.1.2 Uji ADF

tseries::adf.test(train_nvda.ts)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  train_nvda.ts
## Dickey-Fuller = -0.81763, Lag order = 6, p-value = 0.9594
## alternative hypothesis: stationary

\(H_0\) : Data tidak stasioner dalam rataan

\(H_1\) : Data stasioner dalam rataan

Berdasarkan uji ADF tersebut, didapat p-value sebesar \(0.9594\) yang lebih besar dari taraf nyata \(5\%\) sehingga tak tolak \(H_0\) dan menandakan bahwa data tidak stasioner dalam rataan. Hal ini sesuai dengan hasil eksplorasi menggunakan plot time series dan plot ACF, sehingga ketidakstasioneran model kedepannya harus ditangani.

8.1.3 Plot Box-Cox

index <- seq(1:nrow(nvda))
bc = boxcox(nvda.ts~index, lambda = seq(-2, 4, by=0.01))

#Nilai Rounded Lambda
lambda_nvda <- bc$x[which.max(bc$y)]
#SK
sk_nvda <- bc$x[bc$y > max(bc$y) - 1/2 * qchisq(.95,1)]
cat(" Lambda :", lambda_nvda,
    "\n\n Selang Kepercyaan 95% \n",
    "Batas Bawah :", min(sk_nvda), "\n Batas Atas  :", max(sk_nvda) )
##  Lambda : -0.33 
## 
##  Selang Kepercyaan 95% 
##  Batas Bawah : -0.6 
##  Batas Atas  : -0.05

Gambar di atas menunjukkan nilai rounded value (\(\lambda\)) optimum sebesar \(-0.33\) dan pada selang kepercayaan \(95\%\) nilai memiliki batas bawah \(-0.6\) dan batas atas \(-0.05\). Selang tersebut tidak memuat nilai satu sehingga dapat dikatakan bahwa data saham amazon tidak stasioner dalam ragam.

8.1.4 Penanganan Ketidakstasioneran Data

train_nvda.diff <- diff(train_nvda.ts, differences = 1) 
plot.ts(train_nvda.diff, lty=1, xlab="Periode (Tahun)", 
        col = "green4", lwd = 4,
        main="Plot Difference Saham Amazon")

Berdasarkan plot data deret waktu, terlihat bahwa data sudah stasioner dalam rataan ditandai dengan data bergerak pada nilai tengah tertentu (tidak terdapat trend ataupun musiman pada data).

8.2 Uji Ulang

8.2.1 Plot ACF

acf(train_nvda.diff)

Berdasarkan plot tersebut, terlihat bahwa plot ACF cuts off pada lag ke 7, 11, & 17. Sejalan dengan penanganannya, data sudah stasioner dalam rataan dan ketidakstasioneran data telah berhasil tertangani.

8.2.2 Uji ADF

tseries::adf.test(train_nvda.diff)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  train_nvda.diff
## Dickey-Fuller = -5.8703, Lag order = 6, p-value = 0.01
## alternative hypothesis: stationary

\(H_0\) : Data tidak stasioner dalam rataan

\(H_1\) : Data stasioner dalam rataan

Berdasarkan uji ADF tersebut, didapat p-value sebesar \(0.01\) yang lebih kecil dari taraf nyata \(5\%\) sehingga tolak \(H_0\) atau data stasioner dalam rataan. Hal ini sesuai dengan hasil eksplorasi menggunakan plot time series dan plot ACF, sehingga dalam hal ini ketidakstasioneran data sudah berhasil ditangani dan dapat dilanjutkan ke pemodelan.

8.3 Identifikasi Model

8.3.1 Plot ACF

acf(train_nvda.diff)

Berdasarkan plot tersebut, terlihat bahwa plot ACF cuts off pada lag ke 7, 11, & 17. Maka model tidak dapat di identifikasi dengan plot ACF.

8.3.2 Plot PACF

pacf(train_nvda.diff)

Berdasarkan plot tersebut, terlihat bahwa plot PACF cuts off pada lag ke 7, 11, & 17. Maka model tidak dapat di identifikasi dengan plot PACF.

8.3.3 Plot EACF

eacf(train_nvda.diff)
## AR/MA
##   0 1 2 3 4 5 6 7 8 9 10 11 12 13
## 0 o o o o o o x o o o x  o  o  o 
## 1 x o o o o o o o o o o  o  o  o 
## 2 x x o o o o o o o o o  o  o  o 
## 3 x x x o o o o o o o o  o  o  o 
## 4 x x x x o o o o o o o  o  o  o 
## 5 x o x x x o o o o o o  o  o  o 
## 6 x o x x x x o o o o o  o  o  o 
## 7 x o o x x o o o o o o  o  o  o

Identifikasi model menggunakan plot EACF dilakukan dengan melihat titik sudut kiri segitiga pada pola segitiga nol atas (pola mariks segitiga bawah). Dalam hal ini model tentatif yang terbentuk adalah ARIMA(0,1,1), ARIMA(1,1,1), ARIMA(2,1,2), ARIMA(3,1,3), dst.. Namun karena kemungkinannya sangat banyak, maka akan digunakan function agar menyingkat proses.

8.4 Pendugaan Parameter Model Tentatif

model.tentaif_nvda <- 
  model_tentatif(train_nvda.diff, p_max = 6, d = 1, q_max = 12)
## AR/MA
##   0 1 2 3 4 5 6 7 8 9 10 11 12 13
## 0 o o o o o o x o o o x  o  o  o 
## 1 x o o o o o o o o o o  o  o  o 
## 2 x x o o o o o o o o o  o  o  o 
## 3 x x x o o o o o o o o  o  o  o 
## 4 x x x x o o o o o o o  o  o  o 
## 5 x o x x x o o o o o o  o  o  o 
## 6 x o x x x x o o o o o  o  o  o 
## 7 x o o x x o o o o o o  o  o  o 
## 
## Model ARIMA dengan AIC terkecil:
## Series: data 
## ARIMA(4,1,5) 
## 
## Coefficients:
##           ar1     ar2      ar3      ar4      ma1      ma2     ma3     ma4
##       -0.4359  0.2848  -0.4540  -0.8928  -0.5707  -0.7204  0.7219  0.5928
## s.e.   0.0322  0.0322   0.0305   0.0306   0.0227   0.0234  0.0275  0.0242
##           ma5
##       -0.9844
## s.e.   0.0258
## 
## sigma^2 = 53.82:  log likelihood = -1069.37
## AIC=2158.74   AICc=2159.47   BIC=2196.2
datatable(model.tentaif_nvda, filter = 'top', 
          options = list(pageLength = 5))

Berdasarkan pendugaan parameter di atas, nilai AIC terkecil \(2158.74\) dimiliki oleh model ARIMA(4,1,5) dan seluruh parameternya signifikan sehingga model yang dipilih adalah model ARIMA(4,1,5).

model_nvda.da <- Arima(train_nvda.diff, order=c(4,1,5), method="ML")

8.5 Analisis Sisaan

Model terbaik hasil identifikasi kemudian dicek asumsi sisaannya. Sisaan model ARIMA harus memenuhi asumsi normalitas, kebebasan sisaan, dan kehomogenan ragam. Diagnostik model dilakukan secara eksplorasi dan uji formal.

8.5.1 Eksplorasi Sisaan

#Eksplorasi 
sisaan_nvda.da <- model_nvda.da$residuals 
par(mfrow=c(2,2)) 
# QQ-Plot
qqnorm(sisaan_nvda.da) 
qqline(sisaan_nvda.da, col = "dodgerblue3", lwd = 2.5) 
# Plot sisaan
plot(c(1:length(sisaan_nvda.da)), sisaan_nvda.da, 
     main = "Plot Sisaan Model ARIMA",
     xlab = "Periode",
     ylab = "Nilai Sisaan")
abline(h = 0, col = "firebrick2", lty = 2, lwd=2.5)
#Plot ACF dan PACF
acf(sisaan_nvda.da) 
pacf(sisaan_nvda.da) 

Berdasarkan plot kuantil-kuantil normal, secara eksplorasi ditunjukkan sisaan menyebar normal ditandai dengan tititk-titiknya cenderung mengikuti garis \(45^{\circ}\). Kemudian dapat dilihat juga lebar pita sisaan yang cenderung sama menandakan bahwa sisaan memiliki ragam yang homogen. Plot ACF dan PACF sisaan ARIMA(4,1,5) juga tidak signifikan pada 20 lag awal yang menandakan saling bebas. Kondisi ini akan diuji lebih lanjut dengan uji formal.

8.5.2 Uji Formal

8.5.2.1 Sisaan Menyebar Normal

ks.test(sisaan_nvda.da,"pnorm")  #tak tolak H0 > sisaan menyebar normal
## 
##  Asymptotic one-sample Kolmogorov-Smirnov test
## 
## data:  sisaan_nvda.da
## D = 0.4088, p-value < 2.2e-16
## alternative hypothesis: two-sided

Selain dengan eksplorasi, asumsi tersebut dapat diuji menggunakan uji formal. Pada tahapan ini uji formal yang digunakan untuk normalitas adalah uji Kolmogorov-Smirnov (KS). Hipotesis pada uji KS adalah sebagai berikut.

\(H_0\) : Sisaan menyebar normal

\(H_1\) : Sisaan tidak menyebar normal

Berdasarkan uji KS tersebut, didapat p-value sebesar \(2.2\times 10^{-16}\) yang kurang dari taraf nyata \(5\%\) sehingga tolak \(H_0\) dan menandakan bahwa sisaan tidak menyebar normal. Hal ini sesuai dengan hasil eksplorasi menggunakan plot kuantil-kuantil normal.

8.5.2.2 Sisaan saling bebas/tidak ada autokorelasi

Box.test(sisaan_nvda.da, type = "Ljung")  #tak tolak H0 > sisaan saling bebas
## 
##  Box-Ljung test
## 
## data:  sisaan_nvda.da
## X-squared = 0.65354, df = 1, p-value = 0.4189

Selanjutnya akan dilakukan uji formal untuk kebebasan sisaan menggunakan uji Ljung-Box. Hipotesis yang digunakan adalah sebagai berikut.

\(H_0\) : Sisaan saling bebas

\(H_1\) : Sisaan tidak tidak saling bebas

Berdasarkan uji Ljung-Box tersebut, didapat p-value sebesar \(0.4189\) yang lebih besar dari taraf nyata \(5\%\) sehingga tak tolak \(H_0\) dan menandakan bahwa sisaan saling bebas. Hal ini sesuai dengan hasil eksplorasi menggunakan plot ACF dan PACF.

8.5.2.3 Sisaan homogen

Box.test((sisaan_nvda.da)^2, type = "Ljung")  #tak tolak H0 > sisaan homogen
## 
##  Box-Ljung test
## 
## data:  (sisaan_nvda.da)^2
## X-squared = 1.8177, df = 1, p-value = 0.1776

Hipotesis yang digunakan untuk uji kehomogenan ragam adalah sebagai berikut.

\(H_0\) : Ragam sisaan homogen

\(H_1\) : Ragam sisaan tidak homogen

Berdasarkan uji Ljung-Box terhadap sisaan kuadrat tersebut, didapat p-value sebesar \(0.1776\) yang lebih besar dari taraf nyata \(5\%\) sehingga tolak \(H_0\) dan menandakan bahwa ragam sisaan homogen.

8.5.2.4 Nilai tengah sama dengan nol

#4) Nilai tengah sisaan sama dengan nol 
t.test(sisaan_nvda.da, mu = 0, conf.level = 0.95)  #tak tolak h0 > nilai tengah sisaan sama dengan 0
## 
##  One Sample t-test
## 
## data:  sisaan_nvda.da
## t = 1.8162, df = 313, p-value = 0.07029
## alternative hypothesis: true mean is not equal to 0
## 95 percent confidence interval:
##  -0.06142354  1.53582790
## sample estimates:
## mean of x 
## 0.7372022

Terakhir, dengan uji-t, akan dicek apakah nilai tengah sisaan sama dengan nol. Hipotesis yang diujikan sebagai berikut.

\(H_0\) : nilai tengah sisaan sama dengan 0

\(H_1\) : nilai tengah sisaan tidak sama dengan 0

Berdasarkan uji-ttersebut, didapat p-value sebesar \(0.07029\) yang lebih besar dari taraf nyata \(5\%\) sehingga tak tolak \(H_0\) dan menandakan bahwa nilai tengah sisaan sama dengan nol.

8.6 Peramalan

8.6.1 Ramal

Peramalan dilakukan menggunakan fungsi forecast() . Contoh peramalan berikut ini dilakukan untuk h hari ke depan.

#---FORECAST---#
ramalan_nvda.da <- forecast::forecast(model_nvda.da, h = h) 
ramalan_nvda.da
##     Point Forecast      Lo 80     Hi 80     Lo 95    Hi 95
## 316     2.99445467  -6.460391 12.449301 -11.46548 17.45439
## 317    -1.02913818 -10.484270  8.425993 -15.48951 13.43124
## 318     0.42773177  -9.027281  9.882745 -14.03246 14.88793
## 319    -3.54974525 -13.008200  5.908709 -18.01520 10.91571
## 320     2.17948964  -7.364974 11.723954 -12.41751 16.77649
## 321     1.48033678  -8.066033 11.026707 -13.11958 16.08025
## 322     3.92178324  -5.671468 13.515035 -10.74983 18.59340
## 323     3.60834133  -5.994682 13.211365 -11.07822 18.29490
## 324    -0.35738075  -9.963000  9.248238 -15.04791 14.33315
## 325     0.79766929  -8.808205 10.403543 -13.89325 15.48859
## 326    -2.87250345 -12.485597  6.740591 -17.57446 11.82946
## 327     1.13656741  -8.533790 10.806925 -13.65297 15.92610
## 328     1.36008302  -8.310322 11.030488 -13.42952 16.14969
## 329     3.03944550  -6.662392 12.741283 -11.79823 17.87713
## 330     3.82757068  -5.874825 13.529966 -11.01096 18.66610
## 331     0.28151263  -9.424872  9.987897 -14.56312 15.12615
## 332     1.08958278  -8.617621 10.796786 -13.75630 15.93547
## 333    -2.12959795 -11.845359  7.586163 -16.98857 12.72938
## 334     0.41007351  -9.340208 10.160355 -14.50170 15.32184
## 335     1.18536822  -8.565267 10.936003 -13.72694 16.09768
## 336     2.31080119  -7.460408 12.082011 -12.63297 17.25458
## 337     3.76200778  -6.009694 13.533710 -11.18252 18.70654
## 338     0.83053060  -8.944848 10.605909 -14.11962 15.78068
## 339     1.31841337  -8.458130 11.094956 -13.63352 16.27035
## 340    -1.39270245 -11.177021  8.391616 -16.35653 13.57112
## 341    -0.03669810  -9.839817  9.766420 -15.02927 14.95588
## 342     0.99589727  -8.808566 10.800360 -13.99873 15.99053
## 343     1.72729338  -8.090421 11.545008 -13.28761 16.74219
## 344     3.50734448  -6.313905 13.328594 -11.51296 18.52765
## 345     1.26026977  -8.563378 11.083918 -13.76370 16.28424
## 346     1.49266424  -8.332290 11.317619 -13.53331 16.51864
## 347    -0.70970358 -10.540536  9.121129 -15.74466 14.32526
## 348    -0.25253617 -10.092529  9.587457 -15.30151 14.79643
## 349     0.82169031  -9.020484 10.663864 -14.23062 15.87400
## 350     1.27609360  -8.574544 11.126732 -13.78916 16.34134
## 351     3.14262556  -6.714582 12.999834 -11.93267 18.21792
## 352     1.56255108  -8.295718 11.420820 -13.51437 16.63947
## 353     1.61743256  -8.242179 11.477044 -13.46154 16.69641
## 354    -0.10958752  -9.972961  9.753786 -15.19432 14.97514
## 355    -0.29021177 -10.157509  9.577086 -15.38094 14.80052
## 356     0.68248299  -9.187378 10.552344 -14.41217 15.77713
## 357     0.94218168  -8.933084 10.817448 -14.16073 16.04510
## 358     2.72985628  -7.153799 12.613512 -12.38589 17.84560
## 359     1.74422338  -8.139648 11.628095 -13.37185 16.86030
## 360     1.69658982  -8.188633 11.581812 -13.42155 16.81473
## 361     0.39316640  -9.494041 10.280374 -14.72801 15.51435
## 362    -0.20077860 -10.089422  9.687865 -15.32415 14.92260
## 363     0.58853314  -9.302632 10.479699 -14.53870 15.71577
## 364     0.70966555  -9.184982 10.604313 -14.42289 15.84222
## 365     2.31499165  -7.588511 12.218494 -12.83111 17.46109
## 366     1.82165323  -8.081850 11.725157 -13.32445 16.96775
## 367     1.73414590  -8.170729 11.639021 -13.41405 16.88234
## 368     0.79479451  -9.110860 10.700449 -14.35460 15.94419
## 369    -0.02991345  -9.936000  9.876173 -15.17997 15.12014
## 370     0.54224620  -9.366057 10.450549 -14.61120 15.69569
## 371     0.56261827  -9.347971 10.473207 -14.59432 15.71956
## 372     1.92975761  -7.989128 11.848644 -13.23987 17.09938
## 373     1.81616413  -8.103006 11.735334 -13.35390 16.98623
## 374     1.73492449  -8.185662 11.655511 -13.43730 16.90715
## 375     1.09908156  -8.821656 11.019819 -14.07338 16.27154
## 376     0.18410141  -9.736741 10.104944 -14.98852 15.35672
## 377     0.54015894  -9.382496 10.462814 -14.63523 15.71555
## 378     0.48562291  -9.438579 10.409825 -14.69213 15.66338
## 379     1.59389011  -8.337471 11.525252 -13.59482 16.78260
## 380     1.75051388  -8.181673 11.682701 -13.43946 16.94048
## 381     1.70471763  -8.228953 11.638388 -13.48752 16.89696
## 382     1.31478704  -8.618871 11.248445 -13.87743 16.50701
## 383     0.41114448  -9.522539 10.344828 -14.78111 15.60340
## 384     0.57494746  -9.360159 10.510054 -14.61949 15.76938
## 385     0.46414606  -9.472053 10.400345 -14.73196 15.66025
## 386     1.31749398  -8.624527 11.259515 -13.88752 16.52250
## 387     1.64637682  -8.297047 11.589800 -13.56078 16.85353
## 388     1.65009267  -8.294893 11.595079 -13.55945 16.85964
## 389     1.45360798  -8.491512 11.398728 -13.75614 16.66336
## 390     0.62912513  -9.316009 10.574259 -14.58065 15.83890
## 391     0.63723920  -9.309001 10.583480 -14.57422 15.84870
## 392     0.48480833  -9.462249 10.431866 -14.72790 15.69752
## 393     1.10331874  -8.848275 11.054912 -14.11633 16.32297
## 394     1.52272225  -8.430735 11.476180 -13.69978 16.74522

8.6.2 Plot

data.ramalan_nvda.da <- ramalan_nvda.da$mean
plot(ramalan_nvda.da, xlab="Periode (Tahun)", col = "green4", lwd = 2.5)

Berdasarkan hasil plot ramalan di atas, dapat dilihat bahwa ramalan ARIMA(4,1,5) cenderung stabil hingga akhir periode. Selanjutnya, dapat dicari nilai akurasi antara hasil ramalan dengan data uji sebagai berikut.

pt_1 <- train_nvda.ts[length(train_nvda.ts)] #nilai akhir data latih
hasil.forc.Diff <- data.ramalan_nvda.da
ramal_nvda <- diffinv(hasil.forc.Diff, differences = 1) + pt_1
#has.1 sama hasilnta dengan: cumsum(c(pt_1,hasil.forc.Diff))
ts.plot(train_nvda.ts, ramal_nvda, ylab="Saham Harga (USD)",
        xlab="Periode (Tahun)", 
        col = "green4", lwd = 3.5,
        main="Plot Ramal Saham NVIDIA Selama 79 Hari Kedepan")

Dapat dilihat bahwa rata-rata harga saham NVIDA diramalkan akan terus Melonjak naik setiap periodenya.

8.6.3 Perbandingan

perbandingan_nvda.da <- matrix(data=c(head(test_nvda.ts, n=h), ramal_nvda[-1]),
                     nrow = h, ncol = 2)
colnames(perbandingan_nvda.da) <- c("Aktual","Hasil Forecast")
datatable(perbandingan_nvda.da, filter = 'top', 
          options = list(pageLength = 5))
akurasi.nvda <- accuracy(ts(ramal_nvda[-1]), head(test_nvda.ts, n=h)) %>%
  as.data.frame() %>%
  cbind(Model = ramalan_nvda.da[["method"]]) %>% 
  relocate(Model, .before = 1)
row.names(akurasi.nvda) <- "NVDA"
akurasi.nvda
##             Model       ME     RMSE    MAE     MPE     MAPE      ACF1 Theil's U
## NVDA ARIMA(4,1,5) 44.89918 67.53425 53.891 9.97762 13.23123 0.9557909  4.483307

Didapatkan nilai MAPE sebesar \(9.299182\%\) (kurang dari \(10\%\)) yang menandakan bahwa hasil peramalan dari model ARIMA(4,1,5) sudah sangat baik.

9 Perbandingan Antar Saham

9.1 Perbandingan Akurasi

akurasi <- rbind(akurasi.aapl, akurasi.amzn, akurasi.goog, akurasi.meta,
                 akurasi.msft, akurasi.nflx, akurasi.nvda) %>%
  mutate(Keterangan = case_when(
    MAPE < 10 ~ "Sangat Baik",
    MAPE >= 10 & MAPE <= 20 ~ "Baik",
    MAPE > 20 & MAPE <= 50 ~ "Layak",
    MAPE > 50 ~ "Tidak Akurat"
  )) %>% relocate(Keterangan, .before = 1)

datatable(akurasi, filter = 'top', 
          options = list(pageLength = 5))

9.2 Perbandingan Hasil Forcast

9.2.1 Perbandingan Data Train dan Test

chart <-
ggplot(data2, aes(x=Date, y=`Adj Close`, color=Name, alpha=Name)) + #Data
  #Label Data Latih 
  annotate( "rect", alpha=0.1, fill="seagreen",
            xmin=as.Date(min(data2$Date)), 
            xmax=data2$Date[ceiling(0.8 * length(data2$Date)/7)],
            ymin=0, ymax=Inf ) + 
  
  annotate( "text", color="seagreen",
            x = as.Date(data2$Date[ceiling(0.8 * length(data2$Date)/7/2)]), 
            y = max(data2$`Adj Close`) * 0.95, 
    label = "Data Latih\n80%", size=10) + 
  
  #Label Data Uji
  annotate( "rect", alpha=0.1, fill="violetred",
            xmin=data2$Date[ceiling(0.8 * length(data2$Date)/7)], 
            xmax=as.Date(max(data2$Date)),
            ymin=0, ymax=Inf ) + 
  
  annotate( "text", color="violetred",
            x = as.Date(data2$Date[ceiling(0.9 * length(data2$Date)/7)]) , 
            y = max(data2$`Adj Close`) * 0.95, 
    label = "Data Uji\n20%", size=10) +
  
  geom_line(aes(color=Name), linewidth=1.5) + #Timeseries
  #Color
  scale_color_manual(values = c(NVDA="green4", NFLX="firebrick3", 
                                MSFT="deepskyblue2", META="dodgerblue3", 
                                AAPL="lightskyblue4",
                                GOOG="gold3", AMZN="orange2") ) +
  
    scale_alpha_manual(values = c("NVDA" = 1, "NFLX" = 1, "MSFT" = 1, 
                                "META" = 1, "AAPL" = 1, "GOOG" = 1, 
                                "AMZN" = 1)) +
  theme.ts + #THeme
  labs(x = "\nPeriode (Tahun)", y='Harga Saham (USD)',
       title = "Time Series MAANG",
       subtitle = "Pembagian Data Latih dan data Uji\n") +
  # Label / legend
  geom_text_repel(
    data=data2[data2$Date == max(data2$Date),], #Posisi di ujung data
    aes(color = Name, label = Name), #Warna garis & label saham
    size = 8, #Ukuran text
    nudge_x = 20, #Posisi Text (kanan 50)
    hjust = 0, #Ujung
    segment.size = 1,               #Ukuran garis
    segment.alpha = .75,             #transparasi garis
    segment.linetype = "dotted",    #Time garis
    box.padding = .4, #Biar label saham nggak dempetan
    segment.curvature = -0.1, #biar garis mulus
    segment.ncp = 8, 
    segment.angle = 60 
  ) +
  #Axis
    coord_cartesian(clip = "off"
  ) +
    scale_x_date( #Sumbu x
    date_breaks = "1 year",  # Menampilkan label setiap tahun
    date_labels = "%Y",  # Format label tahun
    limits = c(as.Date(min(data2$Date)), as.Date("2023-09-28"))
  ) +
    scale_y_continuous( #Sumbu y
    labels = scales::dollar_format(prefix = "$") #tambahin dolar
  ) +
    annotate( #Buat nandain batas data
    "text", x = as.Date("2023-7-28"), y = 50, 
    label = "28 Juli", size=6
  ) +
  geom_vline( #Buat garis batas data
    xintercept = data2$Date[ceiling(0.8 * length(data2$Date)/7)] , 
             linetype = "dotted", color = "black", linewidth = 2) 
            
chart

#Export Chart
ggsave("09_banding_train-test.png", chart, path = export.chart,
        dpi = 300, height = 12, width = 23)

Dari Semua data ujinya memiliki pola yang cenderung tren naik.

9.2.2 Perbandingan Data Hasil Forcast

#Pnggabungan data
data3 <- data.frame(
  Date = data2 %>% dplyr::select(Date)  ,
  `Adj Close` = c(as.vector(train_aapl.ts), ramal_aapl[-1],
                  as.vector(train_amzn.ts), ramal_amzn[-1],
                  as.vector(train_goog.ts), ramal_goog[-1],
                  as.vector(train_meta.ts), ramal_meta[-1],
                  as.vector(train_msft.ts), ramal_msft[-1],
                  as.vector(train_nflx.ts), ramal_nflx[-1],
                  as.vector(train_nvda.ts), ramal_nvda[-1] ),
  Name = rep(c("AAPL", "AMZN", "GOOG", "META", "MSFT", "NFLX", "NVDA"), 
              each = length(train_aapl.ts) + h)
)
colnames(data3) <- c("Date", "Adj Close", "Name")
chart <- 
ggplot(data3, aes(x = Date, y = `Adj Close`, color = Name)) +
  #Label Data Asli 
  annotate( "rect", alpha=0.1, fill="seagreen",
            xmin=as.Date(min(data3$Date)), 
            xmax=as.Date(data3$Date[ceiling(nrow(train_aapl))]),
            ymin=0, ymax=Inf ) + 
  
  annotate( "text", color="seagreen",
            x = as.Date(data3$Date[ceiling(nrow(train_aapl)/2)]), 
            y = max(data3$`Adj Close`) * 0.95, 
    label = "Data Asli", size=10) + 
  
  #Label Data Ramal
  annotate( "rect", alpha=0.1, fill="violetred",
            xmin=as.Date(data3$Date[ceiling(nrow(train_aapl))]), 
            xmax=as.Date(max(data3$Date)),
            ymin=0, ymax=Inf ) + 
  
  annotate( "text", color="violetred",
            x = as.Date(data3$Date[ceiling(0.9 * length(data3$Date)/7)]) , 
            y = max(data3$`Adj Close`) * 0.95, 
    label = "Data Ramal\n79 Hari", size=10) +
  #Time Series
  geom_line(aes(color=Name), linewidth=1.5) +
  #Warna Saham
  scale_color_manual(values = c(NVDA="green4", NFLX="firebrick3", 
                                MSFT="deepskyblue2", META="dodgerblue3", 
                                AAPL="lightskyblue4",
                                GOOG="gold3", AMZN="orange2") ) +
  theme.ts + #THeme
  labs(x = "\nPeriode (Tahun)", y='Harga Saham (USD)',
       title = "Ramalan Saham MAANG",
       subtitle = "Peramalan Saham MAANG Selama 79 Hari Kedepan\n") +
  # Label / legend
  geom_text_repel(
    data=data3[data3$Date == max(data3$Date),], #Posisi di ujung data
    aes(color = Name, label = Name), #Warna garis & label saham
    size = 8, #Ukuran text
    nudge_x = 20, #Posisi Text (kanan 50)
    hjust = 0, #Ujung
    segment.size = 1,               #Ukuran garis
    segment.alpha = .75,             #transparasi garis
    segment.linetype = "dotted",    #Time garis
    box.padding = .4, #Biar label saham nggak dempetan
    segment.curvature = -0.1, #biar garis mulus
    segment.ncp = 8, 
    segment.angle = 60 
  ) +
  #Axis
    coord_cartesian(clip = "off"
  ) +
    scale_x_date( #Sumbu x
    date_breaks = "1 year",  # Menampilkan label setiap tahun
    date_labels = "%Y",  # Format label tahun
    limits = c(as.Date(min(data3$Date)), 
               as.Date(max(data3$Date)) + 60)
  ) +
    scale_y_continuous( #Sumbu y
    labels = scales::dollar_format(prefix = "$") #tambahin dolar
  ) +
    annotate( #Buat nandain batas data
    "text", x = as.Date("2023-7-28"), y = 50, 
    label = "28 Juli", size=6
  ) +
  geom_vline( #Buat garis batas data
    xintercept = as.Date(data3$Date[ceiling(nrow(train_aapl))]) , 
             linetype = "dotted", color = "black", linewidth = 2)
chart

#Export Chart
ggsave("09_banding_ramal.png", chart, path = export.chart,
        dpi = 300, height = 12, width = 20)